2

I want to refresh a list of elements by using MVVM and data binding but SwipeRefreshLayout doesn't work on XML layout.

BaseViewModel.java

public class BaseViewModel<N> extends ViewModel {
    private final DataManager mDataManager;

    private final ObservableBoolean mIsLoading = new ObservableBoolean(false);

    private final SchedulerProvider mSchedulerProvider;

    private CompositeDisposable mCompositeDisposable;

    private WeakReference<N> mNavigator;

    public BaseViewModel(DataManager dataManager,
                         SchedulerProvider schedulerProvider) {
        this.mDataManager = dataManager;
        this.mSchedulerProvider = schedulerProvider;
        this.mCompositeDisposable = new CompositeDisposable();
    }

    @Override
    protected void onCleared() {
        mCompositeDisposable.dispose();
        super.onCleared();
    }

    public CompositeDisposable getCompositeDisposable() {
        return mCompositeDisposable;
    }

    public DataManager getDataManager() {
        return mDataManager;
    }

    public ObservableBoolean getIsLoading() {
        return mIsLoading;
    }

    public void setIsLoading(boolean isLoading) {
        mIsLoading.set(isLoading);
    }

    public N getNavigator() {
        return mNavigator.get();
    }

    public void setNavigator(N navigator) {
        this.mNavigator = new WeakReference<>(navigator);
    }

    public SchedulerProvider getSchedulerProvider() {
        return mSchedulerProvider;
    }
}

HomeViewModel.java

public class HomeViewModel extends BaseViewModel<HomeNavigator> {
    private  MutableLiveData<ArrayList<HeartRateResultsModel>> heartRateResultsLiveData;

    public HomeViewModel(DataManager dataManager, SchedulerProvider schedulerProvider) {
        super(dataManager, schedulerProvider);
        heartRateResultsLiveData = new MutableLiveData<>();
        fetchRepos();
    }
    public void fetchRepos() {
        setIsLoading(true);
        getCompositeDisposable().add(getDataManager()
                .getHeartRateResults()
                .subscribeOn(getSchedulerProvider().io())
                .observeOn(getSchedulerProvider().ui())
                .subscribe(heartRateResultsModels -> {
                    heartRateResultsLiveData.setValue(heartRateResultsModels);
                    setIsLoading(false);
                }, throwable -> {
                    setIsLoading(false);
                    getNavigator().handleError(throwable);
                }));
    }

    public LiveData<ArrayList<HeartRateResultsModel>> getHeartRateResultsLiveData() {
        return heartRateResultsLiveData;
    }

    public void onRefresh(){
        Log.d("refresh","oy");
        fetchRepos();
    }
}

fragment_home.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="ir.basamadazmanovin.heartrate.ui.main.home.HomeViewModel" />
    </data>

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

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/fragment_home_toolbar"
                style="@style/Toolbar"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:subtitleTextColor="@color/material_white"
                app:title="@string/app_name"
                app:titleTextAppearance="@style/Toolbar.TitleText"
                app:titleTextColor="@color/material_white" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/fragment_home_recyclerView"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:layout_marginEnd="8dp"
                app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/fragment_home_toolbar"
                app:spanCount="3" />


        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</layout>

app:onRefreshListener="@{()-> viewModel.onRefresh()}"

this is where I added the code. also app:refreshing="@{viewModel.isLoading}" work properly but I am seeking for a listener which can detect what the user wants. in Addition, onRefresh() didn't get called when the user refresh

Omid Erfanmanesh
  • 547
  • 1
  • 7
  • 29

1 Answers1

0

You can try to refresh the layout by implementing setOnRefreshListener inside the activity and not the view model. Inside the implementation part, you can call fetchRepos() using view model, such as : homeViewModel!!.fetchRepos()

Crocsx
  • 2,534
  • 1
  • 28
  • 50
Divya
  • 145
  • 10