刷新MVVM体系结构数据

时间:2018-10-31 14:05:31

标签: android mvvm

我有一个MVVM实现,可以使用Retrofit2,Rxjava和Rxandroid从Internet提取数据。

我的目标是当用户在SwipeRefreshLayout中滑动时刷新数据。这是实现。

NewsFeedFragment.java

@Inject
ViewModelFactory viewModelFactory;
RandomVideosViewModel viewModel;


@Override
public void onAttach(Context context) {
    ((BaseApplication) context.getApplicationContext())
            .getAppComponent()
            .inject(this);
    super.onAttach(context);
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    ... 

    viewModel = ViewModelProviders.of(this, viewModelFactory).get(RandomVideosViewModel.class);

    VideoCardAdapter videoCardAdapter = new VideoCardAdapter(getActivity());

    viewModel.videosList.observe(this, videoCardAdapter::submitList);
    viewModel.networkState.observe(this, videoCardAdapter::setNetworkState);

    mRecyclerView.setAdapter(videoCardAdapter);

    ...
}

RandomVideosViewModel.java

public class RandomVideosViewModel extends ViewModel {

    public LiveData<PagedList<Video>> videosList;
    public LiveData<NetworkState> networkState;

    public RandomVideosViewModel(RandomVideosDataSourceFactory randomVideosDataSourceFactory) {

        networkState = Transformations.switchMap(randomVideosDataSourceFactory.getMutableLiveData(),
                PageKeyedRandomVideosDataSource::getNetworkState);

        PagedList.Config pagedListConfig = (new PagedList.Config.Builder()
                .setEnablePlaceholders(false)
                .setInitialLoadSizeHint(10)
                .setPageSize(10))
                .build();

        videosList = (new LivePagedListBuilder(randomVideosDataSourceFactory, pagedListConfig)).build();
    }

}

RandomVideosDataSourceFactory

public class RandomVideosDataSourceFactory extends DataSource.Factory {

    private MutableLiveData<PageKeyedRandomVideosDataSource> mutableLiveData = new MutableLiveData<>();
    private PageKeyedRandomVideosDataSource pageKeyedRandomVideosDataSource;

    public RandomVideosDataSourceFactory(PageKeyedRandomVideosDataSource pageKeyedRandomVideosDataSource) {
        this.pageKeyedRandomVideosDataSource = pageKeyedRandomVideosDataSource;
    }

    public MutableLiveData<PageKeyedRandomVideosDataSource> getMutableLiveData() {
        return mutableLiveData;
    }

    @Override
    public DataSource create() {
        mutableLiveData.postValue(pageKeyedRandomVideosDataSource);
        return pageKeyedRandomVideosDataSource;
    }
}

PageKeyedRandomVideosDataSource

public class PageKeyedRandomVideosDataSource extends PageKeyedDataSource<Integer, Video> {

    private static final String TAG = "Refresh - PageKeyedRand";

    private CompositeDisposable disposable = new CompositeDisposable();
    private MutableLiveData<NetworkState> networkState = new MutableLiveData<>();
    private MutableLiveData<NetworkState> initialLoading = new MutableLiveData<>();
    private Repository repository;
    private Random random = new Random();
    private int firstPage;
    private List<Integer> usedNumbers = new ArrayList<>();
    private int numbOfTimes = 0;

    public PageKeyedRandomVideosDataSource(Repository repository) {
        this.repository = repository;
    }

    public MutableLiveData<NetworkState> getNetworkState() {
        return networkState;
    }

    public MutableLiveData<NetworkState> getInitialLoading() {
        return initialLoading;
    }

    @Override
    public void
    loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, Video> callback) {
        List<Video> videoList = new ArrayList<>();
        networkState.postValue(NetworkState.LOADING);
        initialLoading.postValue(NetworkState.LOADING);

        firstPage = getFirstPage();
        usedNumbers.add(firstPage);
        numbOfTimes++;

        Log.i(TAG, "loadInitial: Loading page: " + firstPage + " - Size: " + params.requestedLoadSize);

        disposable.add(RxHelper.getObservable(repository.getHomeVideosObservable(params.requestedLoadSize, firstPage))
                .subscribe(requestVideo -> {
                    if (requestVideo != null) {
                        int lastPage = requestVideo.getLastPage();
                        int nextPage = getRandomPage(lastPage);
                        Log.i(TAG, "loadInitial: NextPage: " + nextPage);

                        videoList.addAll(requestVideo.getVideoList());
                        callback.onResult(videoList, null, nextPage);
                        networkState.postValue(NetworkState.LOADED);
                        initialLoading.postValue(NetworkState.LOADED);
                    }
                }, throwable -> {
                    throwable.printStackTrace();
                    networkState.postValue(NetworkState.failed(throwable.getMessage()));
                    initialLoading.postValue(NetworkState.failed(throwable.getMessage()));
                }));
    }

    @Override
    public void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Video> callback) {

    }

    @Override
    public void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Video> callback) {
        Log.i(TAG, "loadAfter: Loading page: " + params.key + " - Size: " + params.requestedLoadSize);
        List<Video> videoList = new ArrayList<>();
        networkState.postValue(NetworkState.LOADING);

        disposable.add(RxHelper.getObservable(repository.getHomeVideosObservable(params.requestedLoadSize, params.key))
                .subscribe(requestVideo -> {
                    if (requestVideo != null) {
                        int lastPage = requestVideo.getLastPage();
                        int nextPage = getRandomPage(lastPage);
                        Log.i(TAG, "loadAfter: NextPage: " + nextPage);

                        videoList.addAll(requestVideo.getVideoList());
                        callback.onResult(videoList, nextPage);
                        networkState.postValue(NetworkState.LOADED);
                    }
                }, throwable -> {
                    throwable.printStackTrace();
                    networkState.postValue(NetworkState.failed(throwable.getMessage()));
                }));
    }

RandomVideosDataSourceFactory只是检索PageKeyedRandomVideosDataSource,而最后一个将数据加载到页面块中。

问题

一旦加载了此数据,当用户使用SwipeRefreshLayout时,我就找不到刷新它的方法。有任何线索吗?

我尝试过的事情

我试图重新创建ViewModel,但似乎它一直在检索相同的实例。

1 个答案:

答案 0 :(得分:1)

通常,最好的方法是将ViewModel中的抽象数据收集到存储库中。

存储库为单例。它具有ViewModel观察到的LiveData。

存储库最初从缓存(例如,Room)获取数据。它还会观察到这些数据。

当您需要一组新的数据(第一次加载,刷新时刷新,甚至是一个Worker)时,可以调用存储库以开始更新缓存。这样会自动更新ViewModel中的数据(以及观察ViewModel的其他任何数据)。