paginglibraryjava_Android官⽅分页组件介绍之Paging的使⽤
详解
Android官⽅分页组件介绍之Paging的使⽤详解
发布时间:2018-04-27 13:47,
浏览次数:1618
, 标签:
Android
Paging
Paging 使您的应⽤程序更容易从数据源中逐渐加载所需的信息,不会因为数据库数据量⼤⽽造成查询时间过长。
概述
在我们的实际项⽬中有⼤量的数据,但是我们常常只需要向⽤户展⽰⼀⼩部分信息。⼀个应⽤中可能会有⼏千个item但是我们常常只需要显⽰⼗⼏个或者⼏⼗个。我们处理不当加载数据时可能会造成APP崩溃。
如果数据被存储或与远程数据库同步,这也会减慢应⽤程序的速度,影响⽤户的体验。
尽管Android APIs可以实现分页加载,但是仍不够完美。
1.CursorAdapter
可以是ListView很容易的加载数据,但是他是运⾏在UI线程的,⽽且Cursor也会在页⾯上出现⽆效的现象,使⽤CursorAdapter还有更多的缺点,详细请查看博客
2.AsyncListUtil允许RecycleView基于position进⾏分页加载,但是不允许⾮position进⾏分页加载,在数据集中强制使⽤null作为修饰符。
Paging解决了这些问题。此库中的⼏个简化了请求数据的过程。这⼏个类还可以和组件化架构进⾏⽆缝对接。
功能
获取数据
使⽤DataSource定义你需要提取分页的数据源。根据使⽤场景使⽤的不同使⽤它不同的⼦类,如下
1.使⽤PageKeyDataSource,让你加载的页⾯插⼊到下⼀个或者以前的key,例如:
例如:你要从⽹络获取社交媒体的帖⼦,你就需要通过nextPage加载到后续的加载中。
2.使⽤ItemKeyDataSource,
如果你需要让使⽤的数据的item从N条增加到N+1条请使⽤。例如:你需要从嵌套评论中获取⼀条评论,需要通过⼀条评论的ID获取下⼀条评论的内容。
3.PositionalDataSource,如果你需要从事数据存储的任意位置来获取数据页,此类⽀持你从任意你选择的位置开始请求item的数据集。⽐如从第1200条返回20条item。
如果使⽤Room来管理数据,就要使⽤DataSource.Factory来初始化PositionalDataSource。如下:
@Query("select * from users WHERE age > :age order by name DESC, id ASC")
DataSource.Factory usersOlderThan(int age);
将数据加载进内存
PagedList类加载的数据来⾃于DataSource。你可以配置⼀次加载多少数据,可以预先获取多少数据,尽量减少加载数据的时间。此类也可以向其他类提供数据更新的信号,⽐如:RecycleView.Adapter⼀样,为RecycleView页允许数据加载。
PagedList在架构使⽤中有如下⼏种⽅式
将数据显⽰到UI上
PagedListAdapter类实现⾃RecycleView.Adapter,并且从PagedList中加载数据。例如:当⼀个新的页⾯被加载PagedListAdapter就会发信号通知RecycleView数据已经到了,然后RecycleView就是显⽰和数据量相等的item,并执⾏适当的动画。
PagedListAdapter对于来⾃⼀个PagedList的下⼀条数据会在后台线程进⾏计算。(例如:将数据库的新数据更新到PagedList中),调⽤notifyItem..()⽅法更新需要的数据列表的内容。然后RecycleView再执⾏必要的更改。例如:item的position的顺序的改变。
观察数据的更新
Paging使⽤下列类来构造PagedList容器实时更新:
1.LivePageListBuilder此类是从DataSource.Factory构建LiveData。如果使⽤Room来管理数据库,Dao可以⽣成
DataSource.Factory,使⽤PositionnalDataSource,如下:
This class generates a LiveData
> from theDataSource.Factory
you provide. If you use the Room persistence library
to
manage your database, the DAO can generate the DataSource.Factory
for you, using PositionalDataSource
, as shown in the following example:
LiveData> pagedItems = LivePagedListBuilder(myDataSource, /*
page size */ 50) .setFetchExecutor(myNetworkExecutor) .build();
2.RXPagedListBuilder此类⽀持RXJava。使⽤此类实现PagedList来构造Flowable和Observable如下所⽰:
Flowable> pagedItems = RxPagedListBuilder(myDataSource, /*
page size */ 50) .setFetchScheduler(myNetworkScheduler)
.buildFlowable(BackpressureStrategy.LATEST);
创建数据流
Figure 1.
Paging的数据流是在后台线程⽣产,在UI线程中显⽰。例如:当⼀条新的item插⼊到数据库中,DataSource被初始化,LiveData或者Flowable后台线程就会创建⼀个新的PagedList
Paging在后台线程中完成⼤部分⼯作,所以不会给主线程带来负担。
这个新建的PagedList会被发送到UI线程的PagedListAdapter。PagedListAdapter使⽤DiffUtil在对⽐现在的表单和新建表单的差异。当对⽐结束,PagedListAdapter通过调⽤ifyIte
mInserted()将新的item插⼊到适当的位置。RecycleView就会知道他需要绑定⼀个新的item,并将其显⽰。
数据库案例
1.>LiveDate使⽤
使⽤RecycleView ⾼效的进⾏数据库的增删改查。android retrofit
@Dao interface UserDao { // The Integer type parameter tells Room to use a
PositionalDataSource // object, with position-based loading under the hood.
@Query("SELECT * FROM user ORDER BY lastName ASC") public abstract DataSource.Factory usersByLastName(); } class MyViewModel
extends ViewModel { public final LiveData> usersList; public
MyViewModel(UserDao userDao) { usersList = new LivePagedListBuilder<>( userDao.usersByLastName(), /* page size */ 20).build(); } } class MyActivity
extends AppCompatActivity { private UserAdapter mAdapter; @Override
public void onCreate(Bundle savedState) { Create(savedState); MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class); RecyclerView recyclerView = findViewById(R.id.user_list); mAdapter = new UserAdapter(); viewModel.usersList.observe(this, pagedList ->
mAdapter.submitList(pagedList)); recyclerView.setAdapter(mAdapter); } } class UserAdapter extends PagedListAdapter { public
UserAdapter() { super(DIFF_CALLBACK); } @Override public void
onBindViewHolder(UserViewHolder holder, int position) { User user =
getItem(position); if (user != null) { holder.bindTo(user); } else { // Null
defines a placeholder item - PagedListAdapter will automatically invalidate //
this row when the actual object is loaded from the database holder.clear(); } }
public static final DiffUtil.ItemCallback DIFF_CALLBACK = new
DiffUtil.ItemCallback() { @Override public boolean
areItemsTheSame(@NonNull User oldUser, @NonNull User newUser) { // User properties may have changed if reloaded from the DB, but ID is fixed Id() == Id(); } @Override public boolean
areContentsTheSame(@NonNull User oldUser, @NonNull User newUser) { // NOTE: if you use equals, your object must properly override Object#equals() //
Incorrectly returning false here will result in too many animations. return
oldUser.equals(newUser); } } }
2.>RXJava使⽤
如果使⽤RXJava需要创建Obervabl或者Flowable对象:
class MyViewModel extends ViewModel { public final Flowable>
usersList; public MyViewModel(UserDao userDao) { usersList = new RxPagedListBuilder<>(userDao.usersByLastName(), /* page size */
50).buildFlowable(BackpressureStrategy.LATEST); } }
观察数据的开始和停⽌使⽤如下:
class MyActivity extends AppCompatActivity { private UserAdapter
mAdapter; private final CompositeDisposable mDisposable = new
CompositeDisposable(); @Override public void onCreate(Bundle savedState) {
ViewModelProviders.of(this).get(MyViewModel.class); RecyclerView recyclerView =
findViewById(R.id.user_list); mAdapter = new UserAdapter();
recyclerView.setAdapter(mAdapter); } @Override protected void onStart() {
-> mAdapter.submitList(flowableList))); } @Override protected void onStop() {
UserDao和UserAdapter的代码对于基于rxjava2的解决⽅案是⼀样的,因为它们是基于live数据的解决⽅案
选择数据加载架构
使⽤Paging有两个主要的分页数据⽅式。
⽹络或者数据库
⾸先页⾯加载的数据来⾃于⽹络和数据库⼆者之⼀。如上所⽰,使⽤LiveData将数据加载进UI中。需要指定⼀个元数据传递DataSource.Factory⾄LivePagedListBuilder。
Figure 2.DataSource提供⼀个单⼀的元数据,Factory加载内容。
观察⼀个数据库时,数据库内容发⽣改变数据库就会pull⼀个新的PagedList。
下拉刷新加载⽹络加载时(后端不发送更新)会pull⼀个新的PagedList并使旧的⽆效。
以上这两种⽅式的数据都是异步加载的。
怎么通过实现DataSource.Factory+Retrofit ⽹络加载处理下拉刷新,⽹络异常,和重试PagingWithNetworkSample
⽹络和数据库
实例⼆,加载本地存储页,它本⾝会从⽹络加载附加数据。这通常是为了最⼩化⽹络负载并提供更好的低连接性体验——数据库被⽤作存储在后端的数据的缓存。
如图,LiveData从数据库获取⼀个连接,然后通过LivePagedListBuilder⾄
BoundaryCallback,最后观察到数据完成的信号。
Figure 3.数据库时⽹络数据的缓存,UI是从数据库中加载,如果数据库中没有再从⽹络中获取。
然后在回调中请求⽹络,将这些数据直接储存在数据库中。UI订阅了数据库的更新,因此,新的数据会⾃动流向正在观察的UI。
怎么通过实现DataSource.Factory+Retrofit ⽹络加载处理下拉刷新,⽹络异常,和重试PagingWithNetworkSample

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。