Android Jetpack元件之Paging Library使用篇
highlight: androidstudio theme: jzman
PS:原文首發於微信公眾號:躬行之
閱讀本文之前,可先閱讀同系列 Android Jetpack 元件文章如下 :
- Android Jetpack元件之Lifecycle篇
- Android Jetpack元件之LiveData詳解
- Android Jetpack元件之ViewModel篇
- Android Jetpack元件之DataBinding詳解
- Android Jetpack元件之使用可觀察的資料物件
本文將介紹 Paging Library 庫的使用,其原始碼解析將在下篇文章中介紹,Paging Library 元件是 Android Jetpack 的一部分,是 Google 退出的官方分頁元件,如果專案中使用了 Google 新推出的官方架構元件,如 LiveData、Lifecycle、ViewModel 等,就可以嘗試將該分頁元件引入自己的專案,它的優點是無痕載入更多資料,一定程度上提高使用者體驗。
簡述一下使用 pageing 元件分頁載入資料的過程,DataSource 負責從網路或資料庫載入資料,將資料儲存在 PagedList 中,使用 submitList 提交資料到 PagedListAdapter,當資料發生變化時會在後臺執行緒中計算資料差異,最後 PagedListAdapter 通知 RecyclerView 更新資料。
- 準備資料
- 引入Paging Library元件
- 自定義DataSource
- 配置分頁引數
- 載入顯示資料
- 測試效果
- Paging Library原始碼解析
準備資料
這裡使用乾貨集中營的開源 Api 來進行測試,具體如下:
java
public interface CommonAPI {
// 這裡使用乾貨集中營開源API:http://gank.io/api/search/query/listview/category/Android/count/10/page/1
@GET("api/search/query/listview/category/Android/count/8/page/{page}")
Call<List<DataBean.ResultsBean>> getArticleList1(@Path("page") int page);
}
引入Paging Library元件
引入 Paging Library 庫如下:
java
def paging_version = "2.1.0"
// androidx
implementation "androidx.paging:paging-runtime:$paging_version"
// 老版本 (page library 2.0.0-rc01)
implementation "android.arch.paging:runtime:$paging_version"
這裡使用的時 androidx 最新版本。
自定義DataSource
自定義 DataSource 載入資料,這裡載入的網路資料,使用 PageKeyedDataSource 更合適,繼承 PageKeyedDataSource 自定義 DataSource 如下:
```java
// 自定義DataSource
public class MDataSource extends PageKeyedDataSource
private int mPage = 1;
public MDataSource() {
}
// 初始化
@Override
public void loadInitial(@NonNull LoadInitialParams<String> params,
@NonNull final LoadInitialCallback<String, DataBean.ResultsBean> callback) {
Log.i(TAG, "--loadInitial-->");
CommonAPI api = RetrofitApi.getInstance().mRetrofit.create(CommonAPI.class);
Call<List<DataBean.ResultsBean>> call = api.getArticleList1(mPage);
call.enqueue(new Callback<List<DataBean.ResultsBean>>() {
@Override
public void onResponse(Call<List<DataBean.ResultsBean>> call, Response<List<DataBean.ResultsBean>> response) {
Log.i(TAG, "--onResponse-->" + response.toString());
if (response.isSuccessful() && response.code() == 200) {
List<DataBean.ResultsBean> data = response.body();
callback.onResult(data, "before", "after");
}
}
@Override
public void onFailure(Call<List<DataBean.ResultsBean>> call, Throwable t) {
Log.i(TAG, "--onFailure-->" + t.getMessage());
}
});
}
// 載入上一頁
@Override
public void loadBefore(@NonNull LoadParams<String> params,
@NonNull LoadCallback<String, DataBean.ResultsBean> callback) {
Log.i(TAG, "--loadBefore-->" + params.key);
}
// 載入下一頁
@Override
public void loadAfter(@NonNull final LoadParams<String> params,
@NonNull final LoadCallback<String, DataBean.ResultsBean> callback) {
Log.i(TAG, "--loadAfter-->" + params.key);
mPage++;
CommonAPI api = RetrofitApi.getInstance().mRetrofit.create(CommonAPI.class);
Call<List<DataBean.ResultsBean>> call = api.getArticleList1(mPage);
call.enqueue(new Callback<List<DataBean.ResultsBean>>() {
@Override
public void onResponse(Call<List<DataBean.ResultsBean>> call, Response<List<DataBean.ResultsBean>> response) {
Log.i(TAG, "--onResponse-->" + response.toString());
if (response.isSuccessful() && response.code() == 200) {
List<DataBean.ResultsBean> data = response.body();
callback.onResult(data, params.key);
}
}
@Override
public void onFailure(Call<List<DataBean.ResultsBean>> call, Throwable t) {
Log.i(TAG, "--onFailure-->" + t.getMessage());
}
});
}
} ```
很簡單沒有什麼多餘的東西,細節可以參考後文中的原始碼解析,建立一個工廠方便資料變化是建立新的 DataSource 如下:
```java
// MDataSource建立工廠
public class MDataSourceFactory extends DataSource.Factory
@NonNull
@Override
public DataSource<String, DataBean.ResultsBean> create() {
MDataSource mDataSource = new MDataSource();
return mDataSource;
}
} ```
配置分頁引數
在 ViewModel 中建立 PagedList.Config 並進行分頁引數配置,建立 DataSource 工廠物件,最終生成支援分頁的 LiveData 資料,具體參考如下:
```java // ViewModel public class MViewModel extends ViewModel {
private int pageSize = 20;
// PagedList配置
private PagedList.Config config = new PagedList.Config.Builder()
.setInitialLoadSizeHint(pageSize)//設定首次載入的數量
.setPageSize(pageSize)//設定每頁載入的數量
.setPrefetchDistance(2)//設定距離每頁最後資料項來時預載入下一頁資料
.setEnablePlaceholders(false)//設定是否啟用UI佔用符
.build();
// DataSource.Factory
private DataSource.Factory<String,DataBean.ResultsBean> factory = new MDataSourceFactory();
// LiveData
private LiveData<PagedList<DataBean.ResultsBean>> mPagedList = new LivePagedListBuilder<>(factory, config)
.build();
public LiveData<PagedList<DataBean.ResultsBean>> getPagedList() {
return mPagedList;
}
} ```
載入顯示資料
這裡使用 LiveData 監聽載入的資料,然後使用 sumbitList 將資料提交給 PagedListAdapter,會在後臺執行緒中對比新舊資料的差異,最後更新 RecyclerView ,具體如下:
```java public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private RecyclerView mRecyclerView; private ArticleAdapter mAdapter; private MViewModel mViewModel;
private static DiffUtil.ItemCallback<DataBean.ResultsBean> itemCallback = new DiffUtil.ItemCallback<DataBean.ResultsBean>() {
@Override
public boolean areItemsTheSame(@NonNull DataBean.ResultsBean oldItem, @NonNull DataBean.ResultsBean newItem) {
return oldItem.getGanhuo_id() == newItem.getGanhuo_id();
}
@Override
public boolean areContentsTheSame(@NonNull DataBean.ResultsBean oldItem, @NonNull DataBean.ResultsBean newItem) {
return oldItem.equals(newItem);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = findViewById(R.id.rvData);
mAdapter = new ArticleAdapter(itemCallback);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(mAdapter);
ViewModelProvider mViewModelProvider = new ViewModelProvider(this,
new ViewModelProvider.AndroidViewModelFactory(getApplication()));
mViewModel = mViewModelProvider.get(MViewModel.class);
}
public void getData(View view) {
mViewModel.getPagedList().observe(this, new Observer<PagedList<DataBean.ResultsBean>>() {
@Override
public void onChanged(PagedList<DataBean.ResultsBean> dataBeans) {
Log.i(TAG, "--onChanged-->");
mAdapter.submitList(dataBeans);
}
});
}
} ```
測試效果
可以關注公眾號:躬行之 交流學習。
- Android Jetpack元件之Paging Library使用篇
- Android原生編解碼介面MediaCodec詳解
- Camera2、MediaCodec錄製mp4
- Android多程序執行機制及IPC
- Flutter系列之圖片載入詳解
- Flutter系列之Flex佈局詳解
- Flutter系列之Navigator元件使用
- Material Design元件之NavigationView
- 編譯時註解詳解及實現ButterKnife
- Spring Boot系列MyBatis配置詳解
- Material Design元件之CollapsingToolbarLayout
- Spring Boot系列之JDBC操作資料庫
- Spring Boot系列之專案國際化
- Spring Boot系列之Thymeleaf常用語法
- Spring Boot系列之開發一個介面
- Android Jetpack元件之BindingAdapter詳解
- Android Jetpack元件之DataBinding詳解
- Android Jetpack元件之ViewModel篇