類似情侶空間的網(wǎng)站開發(fā)制作網(wǎng)站平臺
不嘗世間醋與墨,怎知人間酸與苦。
擇一業(yè)謀食養(yǎng)命,等一運(yùn)扭轉(zhuǎn)乾坤。
你見過哪些令你膛目結(jié)舌的代碼技巧?
文章目錄
- 不嘗世間醋與墨,怎知人間酸與苦。
- 擇一業(yè)謀食養(yǎng)命,等一運(yùn)扭轉(zhuǎn)乾坤。
- 你見過哪些令你膛目結(jié)舌的代碼技巧?
- 一,定義
- 二,優(yōu)點(diǎn)
- 三,角色
- 四,PositionalDataSource來源的使用
- 1,添加依賴
- 2,創(chuàng)建bean類
- 3,創(chuàng)建PositionalDataSource來源的數(shù)據(jù)源
- 4,創(chuàng)建數(shù)據(jù)工廠
- 5,創(chuàng)建ViewModel
- 6,創(chuàng)建adapter
- 7,運(yùn)行效果
- 五,ItemKeyedDataSource來源的使用
- 1,創(chuàng)建數(shù)據(jù)倉庫
- 2,創(chuàng)建ItemKeyedDataSource
- 3,創(chuàng)建YuanZhenDataSourceFactory
- 六,PageKeyedDataSource來源的使用
- 1,創(chuàng)建PageKeyedDataSource
- 2,創(chuàng)建數(shù)據(jù)工廠
一,定義
在我們的 Android 項(xiàng)目中使用 RecyclerViews 時,我們會顯示一個包含很多項(xiàng)目的列表。有時我們有一些用例,比如從手機(jī)中獲取聯(lián)系人列表并將其顯示在列表中。在列表中一次加載大量數(shù)據(jù)并不是一項(xiàng)非常有效的任務(wù)。為了克服這個問題,我們在 Android 中進(jìn)行了分頁。 Paging就是google為了分頁而推出的一個庫。Paging庫可以幫助您一次加載和顯示多個小的數(shù)據(jù)塊,按需載入部分?jǐn)?shù)據(jù)可以減少網(wǎng)絡(luò)寬帶和系統(tǒng)資源的使用量。
二,優(yōu)點(diǎn)
①:
分頁庫可以更加輕松地在應(yīng)用程序中的Recyclerview逐步和優(yōu)雅的加載數(shù)據(jù)
?②:數(shù)據(jù)請求消耗的網(wǎng)絡(luò)帶寬更少,系統(tǒng)資源更少
?③:即使在數(shù)據(jù)更新和刷新期間,應(yīng)用程序仍會繼續(xù)快速響應(yīng)用戶輸入 ?
④:不過多浪費(fèi),顯示多少就用多少
三,角色
①:DataSource(數(shù)據(jù)源,包含了多種形式,例如:Room來源,PositionalDataSource來源,PageKeyedDataSource來源,ItemKeyedDataSource來源)
數(shù)據(jù)源就是數(shù)據(jù)的來源,可以有多種來源渠道,例如:“網(wǎng)絡(luò)數(shù)據(jù)”,“本地數(shù)據(jù)”,“數(shù)據(jù)庫數(shù)據(jù)”
②:PagedList(UIModel數(shù)據(jù)層,通過Factory的方式拿到數(shù)據(jù)源)
創(chuàng)建 管理 數(shù)據(jù)源 的工廠,為什么有一個工廠,除了可以去創(chuàng)建數(shù)據(jù)源之外,為了后續(xù)的擴(kuò)展
③:PagedAdapter(不再是之前使用RecycleView的那種適配器了,而是和Paging配套的PagedListAdapter)
數(shù)據(jù)模型其實(shí)就是 ViewModel,用來管理數(shù)據(jù)
PagedList: 數(shù)據(jù)源獲取的數(shù)據(jù)最終靠PagedList來承載。
對于PagedList,我們可以這樣來理解,它就是一頁數(shù)據(jù)的集合。
每請求一頁,就是新的一個PagedList對象。
④:RecycleView(我們之前一直用的RecycleView,只不過setAdapter的時候,綁定的適配器是 PagedAdapter)
這個Adapter就是一個RecyclerView的Adapter。
不過我們在使用paging實(shí)現(xiàn)RecyclerView的分頁加載效果,
不能直接繼承RecyclerView的Adapter,而是需要繼承PagedListAdapter。
LiveData觀察到的數(shù)據(jù),把感應(yīng)到的數(shù)據(jù) 給 適配器,適配器又綁定了 RecyclerView,那么RecyclerView的列表數(shù)據(jù)就改變了
四,PositionalDataSource來源的使用
1,添加依賴
implementation 'androidx.paging:paging-runtime:2.1.0'
2,創(chuàng)建bean類
public class YuanZhen {private String id;private String name;private String age;public void setId(String id) {this.id = id;}public String getId() {return id;}public void setName(String name) {this.name = name;}public void setAge(String age) {this.age = age;}public String getName() {return name;}public String getAge() {return age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;YuanZhen student = (YuanZhen) o;return id.equals(student.id) &&name.equals(student.name) &&age.equals(student.age);}// 比較的函數(shù)@RequiresApi(api = Build.VERSION_CODES.KITKAT)@Overridepublic int hashCode() {return Objects.hash(id, name, age);}
}
3,創(chuàng)建PositionalDataSource來源的數(shù)據(jù)源
public class YuanZhenDataSource extends PositionalDataSource<YuanZhen> {/*** 加載第一頁數(shù)據(jù)的時候,會執(zhí)行此函數(shù)來完成* 加載初始化數(shù)據(jù),加載的是第一頁的數(shù)據(jù)。* 形象的說,當(dāng)我們第一次打開頁面,需要回調(diào)此方法來獲取數(shù)據(jù)。*/@Overridepublic void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<YuanZhen> callback) {callback.onResult(getStudents(0, 20), 0, 1000);}/*** 當(dāng)有了初始化數(shù)據(jù)之后,滑動的時候如果需要加載數(shù)據(jù)的話,會調(diào)用此方法。*/@Overridepublic void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallback<YuanZhen> callback) {callback.onResult(getStudents(params.startPosition, params.loadSize));}/*** 數(shù)據(jù)源,數(shù)據(jù)的來源(數(shù)據(jù)庫,文件,網(wǎng)絡(luò)服務(wù)器響應(yīng) 等等)*/private List<YuanZhen> getStudents(int startPosition, int pageSize) {List<YuanZhen> list = new ArrayList<>();for (int i = startPosition; i < startPosition + pageSize; i++) {YuanZhen yuanZhen = new YuanZhen();yuanZhen.setName("袁震:" + i);yuanZhen.setAge("年齡:" + i);list.add(yuanZhen);}return list;}
}
4,創(chuàng)建數(shù)據(jù)工廠
public class YuanZhenDataSourceFactory extends DataSource.Factory<Integer,YuanZhen> {@NonNull@Overridepublic DataSource<Integer, YuanZhen> create() {YuanZhenDataSource yuanZhenDataSource =new YuanZhenDataSource();return yuanZhenDataSource;}
}
5,創(chuàng)建ViewModel
public class YuanZhenViewModel extends ViewModel {private final LiveData<PagedList<YuanZhen>> listLiveData;public YuanZhenViewModel() {YuanZhenDataSourceFactory factory = new YuanZhenDataSourceFactory();// 初始化 ViewModelthis.listLiveData = new LivePagedListBuilder<Integer, YuanZhen>(factory, 20).build();}public LiveData<PagedList<YuanZhen>> getListLiveData() {return listLiveData;}
}
6,創(chuàng)建adapter
public class RecyclerPagingAdapter extends PagedListAdapter<YuanZhen,RecyclerPagingAdapter.MyRecyclerViewHolder> {private static DiffUtil.ItemCallback<YuanZhen> DIFF_STUDNET = newDiffUtil.ItemCallback<YuanZhen>() {// 一般是比較 唯一性的內(nèi)容, ID@Overridepublic boolean areItemsTheSame(@NonNull YuanZhen oldItem, @NonNull YuanZhen newItem) {return oldItem.getId().equals(newItem.getId());}// 對象本身的比較@Overridepublic boolean areContentsTheSame(@NonNull YuanZhen oldItem, @NonNull YuanZhen newItem) {return oldItem.equals(newItem);}};protected RecyclerPagingAdapter() {super(DIFF_STUDNET);}@NonNull@Overridepublic MyRecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, null);return new MyRecyclerViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull MyRecyclerViewHolder holder, int position) {YuanZhen yuanzhen = getItem(position);// item view 出來了, 分頁庫還在加載數(shù)據(jù)中,我就顯示 Id加載中if (null == yuanzhen) {holder.tvName.setText("Name加載中");holder.tvAge.setText("age加載中");} else {holder.tvName.setText(yuanzhen.getName());holder.tvAge.setText(yuanzhen.getAge());}}// Item 優(yōu)化的 ViewHolderpublic static class MyRecyclerViewHolder extends RecyclerView.ViewHolder {TextView tvId;TextView tvName;TextView tvAge;public MyRecyclerViewHolder(View itemView) {super(itemView);tvName = itemView.findViewById(R.id.tv_name); // 名稱tvAge = itemView.findViewById(R.id.tv_age); // 性別}}
}
item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:id="@+id/tv_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="20dp"android:layout_weight="1"android:gravity="center"android:layout_marginLeft="5dp"/><TextViewandroid:id="@+id/tv_age"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="20dp"android:textColor="@android:color/black"android:layout_weight="1"android:gravity="center"android:layout_marginLeft="5dp"/></LinearLayout>
7,使用
public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView;RecyclerPagingAdapter recyclerPagingAdapter;YuanZhenViewModel viewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView = findViewById(R.id.recycle_view);recyclerPagingAdapter = new RecyclerPagingAdapter();viewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(YuanZhenViewModel.class);// LiveData 觀察者 感應(yīng)更新viewModel.getListLiveData().observe(this, new Observer<PagedList<YuanZhen>>() {@Overridepublic void onChanged(PagedList<YuanZhen> students) {// 再這里更新適配器數(shù)據(jù)recyclerPagingAdapter.submitList(students);}});recyclerView.setAdapter(recyclerPagingAdapter);recyclerView.setLayoutManager(new LinearLayoutManager(this));}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recycle_view"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>
7,運(yùn)行效果
五,ItemKeyedDataSource來源的使用
1,創(chuàng)建數(shù)據(jù)倉庫
public class DataRepository {private List<YuanZhen> dataList = new ArrayList<>();public DataRepository() {for (int i = 0; i < 1000; i++) {YuanZhen person = new YuanZhen();person.setName("袁震:" + i);person.setAge("年齡:" + i);dataList.add(person);}}public List<YuanZhen> initData(int size) {return dataList.subList(0, size);}public List<YuanZhen> loadPageData(int page, int size) {int totalPage;if (dataList.size() % size == 0) {totalPage = dataList.size() / size;} else {totalPage = dataList.size() / size + 1;}if (page > totalPage || page < 1) {return null;}if (page == totalPage) {return dataList.subList((page - 1) * size, dataList.size());}return dataList.subList((page - 1) * size, page * size);}
}
2,創(chuàng)建ItemKeyedDataSource
public class CustomItemDataSource extends ItemKeyedDataSource<Integer, YuanZhen> {private DataRepository dataRepository;CustomItemDataSource(DataRepository dataRepository) {this.dataRepository = dataRepository;}// loadInitial 初始加載數(shù)據(jù)@Overridepublic void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.initData(params.requestedLoadSize);callback.onResult(dataList);}@NonNull@Overridepublic Integer getKey(@NonNull YuanZhen item) {return (int) System.currentTimeMillis();}// loadBefore 向前分頁加載數(shù)據(jù)@Overridepublic void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);if (dataList != null) {callback.onResult(dataList);}}// loadAfter 向后分頁加載數(shù)據(jù)@Overridepublic void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);if (dataList != null) {callback.onResult(dataList);}}}
3,創(chuàng)建YuanZhenDataSourceFactory
public class YuanZhenDataSourceFactory extends DataSource.Factory<Integer,YuanZhen> {@NonNull@Overridepublic DataSource<Integer, YuanZhen> create() {return new CustomItemDataSource(new DataRepository());}
}
六,PageKeyedDataSource來源的使用
1,創(chuàng)建PageKeyedDataSource
public class CustomPageDataSource extends PageKeyedDataSource<Integer, YuanZhen> {private DataRepository dataRepository;CustomPageDataSource(DataRepository dataRepository) {this.dataRepository = dataRepository;}// loadInitial 初始加載數(shù)據(jù)@Overridepublic void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.initData(params.requestedLoadSize);callback.onResult(dataList, null, 2);}// loadBefore 向前分頁加載數(shù)據(jù)@Overridepublic void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);if (dataList != null) {callback.onResult(dataList, params.key - 1);}}// loadAfter 向后分頁加載數(shù)據(jù)@Overridepublic void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, YuanZhen> callback) {List<YuanZhen> dataList = dataRepository.loadPageData(params.key, params.requestedLoadSize);if (dataList != null) {callback.onResult(dataList, params.key + 1);}}
}
2,創(chuàng)建數(shù)據(jù)工廠
public class YuanZhenDataSourceFactory extends DataSource.Factory<Integer,YuanZhen> {@NonNull@Overridepublic DataSource<Integer, YuanZhen> create() {return new CustomPageDataSource(new DataRepository());}
}