3

Following How to set SwipeRefreshLayout refreshing property using android data binding? I'm trying to bind SwipeRefreshLayout using data binding but SwipeRefreshLayout's progress is not getting hide. Below is my code that i'm using it:

ViewModel

public class StateViewModel extends BaseViewModel {
 public MutableLiveData<Boolean> isLoading; 

 public void getItemStateDetails() {
    isLoading.setValue(true);
    scanTypePosition.setValue(0);
    getCompositeDisposable().add(
            getRepositoryManager().getItemStates()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(this::onSuccess, this::onError));
} 

private void onError(Throwable throwable) {
    isLoading.setValue(false);
    errorMsg.setValue(throwable.getMessage());
}

  private void onSuccess(List<State> states) {
        isLoading.setValue(false);
        lstState.setValue(states);
    }
}

Layout

     <variable
            name="stateModel"
            type="story.stateupdate.stateselection.StateViewModel" />

     <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                apps:cardUseCompatPadding="true">

                <android.support.v4.widget.SwipeRefreshLayout
                    android:id="@+id/pullToRefresh"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:onRefreshListener="@{() -> stateModel.getItemStateDetails()}"
                    app:refreshing="@{stateModel.isLoading}">

                    <android.support.v7.widget.RecyclerView
                        android:id="@+id/stateRecyclerView"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent" />
                </android.support.v4.widget.SwipeRefreshLayout>
            </android.support.v7.widget.CardView>

In the above code, the variable isLoading is getting changed from true to false but the progress is still visible. Can anyone point out what mistake I'm doing?

Mangesh Pawar
  • 309
  • 1
  • 14
Pranesh saw
  • 83
  • 1
  • 9
  • @Jeel tried but getting error message Cannot find the setter for attribute 'app:isRefreshing' – Pranesh saw Jan 02 '19 at 09:03
  • Why don't you pass your view object to method `getItemStateDetails()` and disable it programmatically there once your condition satisfied? – Jeel Vankhede Jan 02 '19 at 09:15
  • @Jeel since i heard from some developer we should avoid having reference to any kind of view in the viewmodel classes so that we cannot leak memory & make it testable. – Pranesh saw Jan 02 '19 at 09:24
  • Okay, agree with your point. One more thing is that how you're updating view from your BR class. because throughout code, there nothing that notifies about data change to your view. `i.e. notifyPropertyChanged(BR.isLoading)` – Jeel Vankhede Jan 02 '19 at 09:28
  • for now i'm going to do it programatically something like stateFragmentBinding.pullToRefresh.setRefreshing(isLoading); later i will do research why app:refreshing="@{stateModel.isLoading}" is not working. Thanks Jeel. – Pranesh saw Jan 02 '19 at 09:44

2 Answers2

2

I think you should try to update SwipeRefreshLayout through the SwipeRefreshLayout.post() method:

SwipeRefreshLayout.post(new Runnable() {
       @Override
       public void run() {
            SwipeRefreshLayout.setRefreshing(isLoading);
       }
});

Or you can try to create a custom view that extend from SwipeRefreshLayout as below:

public class CustomSwipeRefreshLayout extends SwipeRefreshLayout {
    public CustomSwipeRefreshLayout(@NonNull Context context) {
        super(context);
    }

    public CustomSwipeRefreshLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setRefreshing(final boolean refreshing) {
        post(new Runnable() {
            @Override
            public void run() {
                CustomSwipeRefreshLayout.super.setRefreshing(refreshing);
            }
        });
    }
}
John Le
  • 1,116
  • 9
  • 12
0
public class StateViewModel extends BaseViewModel implements SwipeRefreshLayout.OnRefreshListener {
 SwipeRefreshLayout swipeRefreshLayout;

 public void getItemStateDetails() {
    swipeRefreshLayout.setRefreshing ( true );
    scanTypePosition.setValue(0);
    getCompositeDisposable().add(
            getRepositoryManager().getItemStates()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(this::onSuccess, this::onError));
} 

private void onError(Throwable throwable) {
    swipeRefreshLayout.setRefreshing ( false);
    errorMsg.setValue(throwable.getMessage());
}

  private void onSuccess(List<State> states) {
        swipeRefreshLayout.setRefreshing ( false);
        lstState.setValue(states);
    }
}
Unnati Patadia
  • 662
  • 3
  • 19
  • 39
  • Can't have a reference of SwipeRefreshLayout object in my stateViewModel since there will be chances of leaking memory. – Pranesh saw Jan 02 '19 at 08:57