paging是google推出的分页加载框架,收录在 jetpack开发套件,结合RecycleView使用,开发者只用选择合适的模板实现本身的DataSource(数据存储层,能够是内存/db/网络),框架层实现了自动分页加载的逻辑,详情能够参考官方文档: developer.android.com/topic/libra…android
先来一个简单的示例,分页加载学生列表,模拟了100个学生数据,id从0开始自增,以id为cursor分页加载,每页10条数据 效果以下:缓存
dependencies {
...
implementation ("android.arch.paging:runtime:1.0.1")
implementation 'android.arch.lifecycle:extensions:1.1.1'
}
复制代码
选择合适的DataSource网络
public class StudentDataSource extends ItemKeyedDataSource<String, StudentBean> {
private static final int MIN_STUDENT_ID = 1;
private static final int MAX_STUDENT_ID = 100;
private Random mRandom = new Random();
public StudentDataSource() {
}
@Override
public void loadInitial(@NonNull LoadInitialParams<String> params,
@NonNull LoadInitialCallback<StudentBean> callback) {
List<StudentBean> studentBeanList = mockStudentBean(0L, params.requestedLoadSize);
callback.onResult(studentBeanList);
}
@Override
public void loadAfter(@NonNull LoadParams<String> params, @NonNull LoadCallback<StudentBean> callback) {
long studentId = Long.valueOf(params.key);
int limit = (int)Math.min(params.requestedLoadSize, Math.max(MAX_STUDENT_ID - studentId, 0));
List<StudentBean> studentBeanList = mockStudentBean(studentId + 1, limit);
callback.onResult(studentBeanList);
}
@Override
public void loadBefore(@NonNull LoadParams<String> params, @NonNull LoadCallback<StudentBean> callback) {
long studentId = Long.valueOf(params.key);
int limit = (int)Math.min(params.requestedLoadSize, Math.max(studentId - MIN_STUDENT_ID, 0));
List<StudentBean> studentBeanList = mockStudentBean(studentId - limit, limit);
callback.onResult(studentBeanList);
}
@NonNull
@Override
public String getKey(@NonNull StudentBean item) {
return item.getId();
}
}
复制代码
实现DataSource工厂(可选,Demo使用了LivePagedListBuilder,依赖Factory)数据结构
public class StudentDataSourceFactory extends DataSource.Factory<String, StudentBean> {
@Override
public DataSource<String, StudentBean> create() {
return new StudentDataSource();
}
}
复制代码
生成PageListapp
public class StudentRepositoryImpl implements IStudentRepository {
@Override
public LiveData<PagedList<StudentBean>> getAllStudents() {
int pageSize = 10;
StudentDataSourceFactory dataSourceFactory = new StudentDataSourceFactory();
PagedList.Config pageListConfig = new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setInitialLoadSizeHint(pageSize * 2)
.setPageSize(pageSize)
.build();
return new LivePagedListBuilder<>(dataSourceFactory, pageListConfig)
.build();
}
}
复制代码
mList = new PagedList.Builder<>(mDataSource, config)
.setNotifyExecutor(notifyExecutor)
.setFetchExecutor(fetchExecutor)
.setBoundaryCallback(boundaryCallback)
.setInitialKey(initializeKey)
.build();
复制代码
实现PagedListAdapter框架
public class StudentAdapter extends PagedListAdapter<StudentBean, StudentViewHolder> {
private static final DiffUtil.ItemCallback<StudentBean> DIFF_CALLBACK = new ItemCallback<StudentBean>() {
@Override
public boolean areItemsTheSame(StudentBean oldItem, StudentBean newItem) {
return TextUtils.equals(oldItem.getId(), newItem.getId());
}
@Override
public boolean areContentsTheSame(StudentBean oldItem, StudentBean newItem) {
return oldItem == newItem;
}
};
public StudentAdapter() {
super(DIFF_CALLBACK);
}
@Override
public StudentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.student_item, null, false);
return new StudentViewHolder(itemView);
}
@Override
public void onBindViewHolder(StudentViewHolder holder, int position) {
holder.bindData(getItem(position));
}
复制代码
StudentViewModel viewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
viewModel.getPageListLiveData().observe(this, new Observer<PagedList<StudentBean>>() {
@Override
public void onChanged(@Nullable PagedList<StudentBean> studentBeans) {
studentAdapter.submitList(studentBeans);
}
});
复制代码
大体流程以下:dom
两种类型的PagedList异步
PagedList内部持有如下几个重要成员变量ide
AsyncPagedListDiffer与PagedListAdapter源码分析
理想中的分页加载库只须要用户关注业务数据结构,写少许的代码及UI布局,便可实现分页加载的效果,后续打算基于Paging Libaray封装一套基于"通用分页协议"的"模板代码"