Search code examples
javaandroidandroid-databindingandroid-architecture-componentsandroid-viewmodel

MVVM + Data Binding + View Model not updating view


I've got a strange problem. I want to set refreshing for swipeRefreshLayout depending on loading data. So I've got listener which obtains true/false depending on fetching data. Then it goes to ViewModel where ObservableBoolean is set and thanks to DataBinding it should update refreshLayout. It works.. when the device is connected to the internet.

Here is my listener

        @Override
        public void isLoading(boolean loading) {
            Log.d(TAG, "isLoading: "+loading);
            //binding.slHomeSwipe.setRefreshing(loading); <- this one works
            viewModel.isLoading.set(loading); // I want to use this, but it's not working
        }

Here is my ViewModel. onRefresh() works every time. Log in setLoading() always display the correct value. When I don't have internet connection log displays false, but the refreshing circle don't hide.

public class MainFragmentViewModel extends ViewModel {

...
public ObservableBoolean isLoading;

..init - isLoading = new..

public void onRefresh() {
    Log.d(TAG, "onRefresh: ");
    MainLib.refreshForecast();
}

void setLoading(boolean loading) {
    Log.d(TAG, "setLoading: "+loading);
    this.isLoading.set(loading);
}

And there is my layout. I've put TextView to test if it displaying the correct boolean value, but it is not. It works only when swipeRefreshLayout works.

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_home_main"
...>

<TextView
    android:id="@+id/tv_home_test"
    android:text="@{String.valueOf(viewModel.isLoading)}"
    .../>

<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
    android:id="@+id/sl_home_swipe"
    app:onRefreshListener="@{() -> viewModel.onRefresh()}"
    app:refreshing="@{viewModel.isLoading}"
.../>

    <androidx.recyclerview.widget.RecyclerView
.../>

I don't think that the reason that it is not working is a network connection. But that is the case I noticed that it is not working. When the app is launching, listener sends value true than false and it's working. But when refreshing is started by swiping, it doesn't work. My suspicion is that the viewModel is disconnected somehow from the layout.


Solution

  • I've got it working!

    The problem was that when I had no internet connection and I refreshed, my listener returned false. This part I'm not sure, but I think that because my ObservableBoolean did not change the state (stayed false), it didn't had an influence on the swiping layout, so swiping layout internally set refreshing to true while my ObservableBoolean was false. So I had to set this value to true just after starting refreshing data.

    This is my ViewModel method

    public void onRefresh() {
        Log.d(TAG, "onRefresh: ");
        MainLib.refreshForecast();
        setLoading(true); // <- I was missing this
    }