我有一个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,但似乎它一直在检索相同的实例。
答案 0 :(得分:1)
通常,最好的方法是将ViewModel中的抽象数据收集到存储库中。
存储库为单例。它具有ViewModel观察到的LiveData。
存储库最初从缓存(例如,Room)获取数据。它还会观察到这些数据。
当您需要一组新的数据(第一次加载,刷新时刷新,甚至是一个Worker)时,可以调用存储库以开始更新缓存。这样会自动更新ViewModel中的数据(以及观察ViewModel的其他任何数据)。