Android Architecture Components 系列(六)Paging Library

Paging Library 分页加载库 
    用于逐步从数据源加载信息,而不会耗费过多的设备资源或是等待太长的时间。
 
现有的分页加载功能的优点 mix 缺陷:
CursorAdapter ,使得从数据库加载数据到ListVIew变得非常容易。
                            但是这是在主线程中查询数据库,并且分也的内容实用低效的Cursor返回。 更多使用CursorAdapter带来的问题参考Large Database Queries on Android
AsyncListUtils  ,提供基于位置的 分页加载到RecycleView中。
                            但是无法使用不基于位置 的分页加载,而且强制把null 作为占位符
 
 DataSource 数据源
    根据想要访问数据的方式,可以有两种子类可供选择:
        KeyedDataSource用于加载从第N到N+1 条数据
        TiledDataSource用于从任意位置的分页数据
 
    例如使用  Room persistence library就可以自动创建返回  TiledDataSource类型的数据:
 
   @Query("select * from users WHERE age > :age order by name DESC, id ASC")
TiledDataSource<User> usersOlderThan(int age);
 
PagedList 定量数据
   从上面DataSource 获取指定数量的数据,并且可以制定预取多少数据。这样可以最大程度减少加载数据的时间。
    ps:这个类提供更新信息给其他类  比如RecyclerView.Adapter来更新 RecyclerView的UI。
 
PagedListAdapter 适配器
    这个类是 RecyclerView.Adapter得到一个实现类,用于当数据加载完毕时,通知Recycle数据1已经到达可以进行加载显示。Recycleview就可以把数据填充进行显示操作。
 
PagedListProvider
    从数据源中产生 LiveData<PagedList>。此外如果使用的是 Room persistence library,DAO还能使用 TiledDataSource生成 LivePagedListProvider。示例代码:
 
        @Query("SELECT * from users order WHERE age > :age order by name DESC, id ASC”)
     public abstract LivePagedListProvider<Integer, User> usersOlderThan(int age);
 
Paging Library从后台线程获取数据流,再在Ui线程中展示就是通过以上几个重要类。
 
流程图:
 
当新的item插入到数据库,DataSource被更新,LivePagedListProvider在后台线程产生了新的PagedList
 
 
    继而,中间新生成的PagedList 在主线程中被发送到PagedListAdapter中,让它使用后台线程DiffUtil计算新的List和原来的List的差距,
当差异比较完后,PagedListAdapter用 RecyclerView.Adapter.notifyItemInserted()来通知数据刷新。
    
    实例代码:
 
/**
* Dao数据库操作
*/
@Dao 
interface UserDao{ 
    @Query("SELECT * FROM user ORDER BY lastName ASC”) 
    public abstractLivePagedListProvider<Integer, User>usersByLastName(); 
/**
* ViewModel 数据源
*/
class MyViewModel extends ViewModel{ 
    public final LiveData<PagedList<User>> usersList ;//数据list 
    public MyViewModel(UserDao userDao) { 
        usersList =userDao.usersByLastName().create( 
           /* initial load position */ 0,
             new PagedList.Config.Builder()
                     .setPageSize(50) 
                    .setPrefetchDistance(50) .build()); 
        }
 }
/**
*  View层的实现
*  初始化ViewModel、RecycleView并绑定PagedListAdapter
* 通过observe方法将ViewMode数据加载到数据List中
*/
 class MyActivity extends AppCompatActivity { 
       @Override 
        public void onCreate(Bundle savedState) { 
            super.onCreate(savedState); 
        MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class); 
        RecyclerViewrecyclerView = findViewById(R.id.user_list); 
       UserAdapter<User> adapter= new UserAdapter();
         viewModel.usersList.observe(this,
                     pagedList -> adapter.setList(pagedList));
         recyclerView.setAdapter(adapter);
         } 
    } 
/**
*  PagedListAdapter 适配器配置
*  覆写onBindViewHolder()方法
*  @param UserViewHolder
*  @param position
    
*/
class UserAdapter extends PagedListAdapter<User, UserViewHolder> { 
        public UserAdapter() { 
            super(DIFF_CALLBACK);
        }
     
    @Override
    public void onBindViewHolder(UserViewHolder holder, int position) { 
        User user = getItem(position); //通过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(); 
        } 
    } 
 
/**
* 后台线程DiffUtil类回调: 计算新的List和原来的List的差距
*/
    public static final  DiffCallback<User> DIFF_CALLBACK = new DiffCallback<User>() { 
            @Override 
            public boolean areItemsTheSame(@NonNull User oldUser, @NonNull User newUser) { 
               // User properties may have changed if reloaded from the DB, but ID is fixed 
                return oldUser.getId() == newUser.getId(); 
            } 
            @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); 
            } 
    } 
}
 
 
PS.鉴于大家的都建议给一个整体框架的demo,这里可以提供一个更好的方案: Google Android Architecture Components,这是Google官方提供的样例可以用来参考。
 
 
 

猜你喜欢

转载自www.cnblogs.com/cold-ice/p/9115858.html