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封裝一套基於"通用分頁協議"的"模板代碼"