我的应用程序正在使用 Android 的 Architecture Components 库,并显示从分页 REST api 获取的项目列表,并具有无限滚动效果。
我想做的是将Paging Library与NetworkBoundResource结合使用,这样当用户向下滚动列表时,将从数据库中获取下一个项目并显示(如果存在),并且同时调用 API 来更新数据库中的项目。
我找不到这两种模式共存的任何例子。
这是 DAO:
@Query("SELECT * FROM items ORDER BY id DESC")
LivePagedListProvider<Integer,MyItem> loadListPaginated();
这是我的
NetworkBoundResource
实现:
public class PagedListNetworkBoundResource extends NetworkBoundResource<PagedList<MyItem>, List<MyItem>> {
@Override
protected void saveCallResult(@NonNull List<MyItem> items) {
// Inserting new items into DB
dao.insertAll(items);
}
@Override
protected boolean shouldFetch(@Nullable PagedList<MyItem> data) {
return true;
}
@NonNull
@Override
protected LiveData<PagedList<MyItem>> loadFromDb() {
return Transformations.switchMap(dao.loadListPaginated().create(INITIAL_LOAD_KEY, PAGE_SIZE),
new Function<PagedList<MyItem>, LiveData<List<MyItem>>>() {
@Override
public LiveData<PagedList<MyItem>> apply(final PagedList<MyItem> input) {
// Here I must load nested objects, attach them,
// and return the fully loaded items
}
});
}
@NonNull
@Override
protected LiveData<ApiResponse<List<MyItem>>> createCall() {
// I don't get the current paged list offset to perform a call to the API
return ...;
}
}
我还搜索了很多有关 NetworkBoundResource 的信息,我得出的结论是 NetworkBoundResource 和 Paging Lib 彼此不相关。它们都有自己的功能
根据谷歌给出的关于分页库的文章 https://developer.android.com/topic/libraries/architecture/paging.html
1.要从本地数据库加载数据,您需要使用DataSource 我的道
@Dao
public interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(User... user);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(List<User> users);
@Query("Select * from User ")
public abstract DataSource.Factory<Integer,User> getList();
}
2.然后从网络请求数据,我们需要使用 LivePagedListBuilder 实现 BoundaryCallback 类
public class UserBoundaryCallback extends PagedList.BoundaryCallback<User> {
public static final String TAG = "ItemKeyedUserDataSource";
GitHubService gitHubService;
AppExecutors executors;
private MutableLiveData networkState;
private MutableLiveData initialLoading;
public UserBoundaryCallback(AppExecutors executors) {
super();
gitHubService = GitHubApi.createGitHubService();
this.executors = executors;
networkState = new MutableLiveData();
initialLoading = new MutableLiveData();
}
public MutableLiveData getNetworkState() {
return networkState;
}
public MutableLiveData getInitialLoading() {
return initialLoading;
}
@Override
public void onZeroItemsLoaded() {
//super.onZeroItemsLoaded();
fetchFromNetwork(null);
}
@Override
public void onItemAtFrontLoaded(@NonNull User itemAtFront) {
//super.onItemAtFrontLoaded(itemAtFront);
}
@Override
public void onItemAtEndLoaded(@NonNull User itemAtEnd) {
// super.onItemAtEndLoaded(itemAtEnd);
fetchFromNetwork(itemAtEnd);
}
public void fetchFromNetwork(User user) {
if(user==null) {
user = new User();
user.userId = 1;
}
networkState.postValue(NetworkState.LOADING);
gitHubService.getUser(user.userId,20).enqueue(new Callback<List<User>>() {
@Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
executors.diskIO().execute(()->{
if(response.body()!=null)
userDao.insert(response.body());
networkState.postValue(NetworkState.LOADED);
});
}
@Override
public void onFailure(Call<List<User>> call, Throwable t) {
String errorMessage;
errorMessage = t.getMessage();
if (t == null) {
errorMessage = "unknown error";
}
Log.d(TAG,errorMessage);
networkState.postValue(new NetworkState(Status.FAILED, errorMessage));
}
});
}
}
3.我的VM代码从DB +网络加载数据
public class UserViewModel extends ViewModel {
public LiveData<PagedList<User>> userList;
public LiveData<NetworkState> networkState;
AppExecutors executor;
UserBoundaryCallback userBoundaryCallback;
public UserViewModel() {
executor = new AppExecutors();
}
public void init(UserDao userDao)
{
PagedList.Config pagedListConfig =
(new PagedList.Config.Builder()).setEnablePlaceholders(true)
.setPrefetchDistance(10)
.setPageSize(20).build();
userBoundaryCallback = new UserBoundaryCallback(executor);
networkState = userBoundaryCallback.getNetworkState();
userList = (new LivePagedListBuilder(userDao.getList(), pagedListConfig).setBoundaryCallback(userBoundaryCallback))
.build();
}
}
这假设回调中的每个项目都包含一个索引/偏移量。通常情况并非如此 - 项目可能只包含 id。