美文网首页
Jetpack学习-7-Paging

Jetpack学习-7-Paging

作者: 主音King | 来源:发表于2020-08-18 09:30 被阅读0次

    Paging是什么

    分页库可一次加载和显示一块数据,按需载入部分数据减少网络带宽和系统资源的使用量。

    简单使用

    引入Paging

    dependencies {
        implementation 'androidx.paging:paging-runtime:2.1.2'
    }
    

    定义Bean

    public class Student {
        private String id;
        private String name;
        private String gender;
    
        public String getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    
        public String getGender() {
            return gender;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Student student = (Student) o;
            return Objects.equals(id, student.id) &&
                    Objects.equals(name, student.name) &&
                    Objects.equals(gender, student.gender);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(id, name, gender);
        }
    }
    

    需要重写equals和hasCode方法,后面比较数据会用到。

    定义DataSource

    /**
     * @author: George.ren
     * date: 2020/8/11
     * PageKeyedDataSource:按页加载
     * ItemKeyedDataSource:按条目加载
     * PositionalDataSource:按位置加载(从n到n+x)
     */
    public class StudentDataSource extends PositionalDataSource<Student> {
        private static final String TAG = "-paging-StudentData";
    
        @Override
        public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<Student> callback) {
            Log.d(TAG, "loadInitial-初始化数据-数据量:" + 10);
            // 模拟数据源;开始位置;总共数据数;
            // 注意:模拟数据源的开始位置最好和 第二个参数开始位置一致。
            // 如果模拟数据源个数小于 第三个参数,则触发分页(loadRange去加载下一页)
            //
            // 如果请求数据大小不符合要求直接crash--》PagedStorage-->insertPage--> page introduces incorrect tiling
            // 例如第三个参数 小于 每页个数
            callback.onResult(getStudents(0, Config.PER_PAGE_SIZE), 0, Config.INIT_SIZE);
            // 可以不写三个参数
    //        callback.onResult(getStudents(0, Config.PER_PAGE_SIZE), 0);
        }
    
        @Override
        public void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallback<Student> callback) {
            Log.d(TAG, "-下一页数据-loadRange-start:" + params.startPosition + " size:" + params.loadSize);
            callback.onResult(getStudents(params.startPosition, params.loadSize));
        }
    
        /**
         * 模拟数据源
         *
         * @param startPosition 开始加载位置
         * @param pageSize      每页个数
         * @return
         */
        private List<Student> getStudents(int startPosition, int pageSize) {
            Log.d(TAG, "模拟数据源-getStudents-startPosition:" + startPosition + " pageSize:"
                    + pageSize + " endPo:" + (startPosition + pageSize - 1));
            List<Student> list = new ArrayList<>();
            for (int i = startPosition; i < startPosition + pageSize; i++) {
                Student student = new Student();
                student.setId("ID:" + i);
                student.setName("名称:" + i);
                student.setGender("性别:" + i);
                list.add(student);
            }
            return list;
        }
    }
    

    定义继承自PositionalDataSource,这是一个固定大小的数据源。
    获取数据方法getStudents,重写loadInitial首次加载数据被调用,loadRange方法(分页加载)

    定义DataSourceFactory

    public class StudentDataSourceFactory extends DataSource.Factory<Integer,Student>{
        @NonNull
        @Override
        public DataSource<Integer, Student> create() {
            StudentDataSource dataSource = new StudentDataSource();
            return dataSource;
        }
    }
    

    工厂模式,控制数据源StudentDataSource

    定义ViewModel

    public class StudentViewModel extends ViewModel {
        private final LiveData<PagedList<Student>> listLiveData;
    
        /**
         * 构造方法赋值
         * 加载第一页数据
         */
        public StudentViewModel() {
            StudentDataSourceFactory factory = new StudentDataSourceFactory();
            // 工厂:创建DataSource对象;每页大小
            this.listLiveData = new LivePagedListBuilder<>(factory, getPageConfig()).build();
        }
    
        private PagedList.Config getPageConfig(){
            return new PagedList.Config.Builder()
                    .setPageSize(Config.PER_PAGE_SIZE) // 分页数据量。DataSource的loadRange中的值
                    .setPrefetchDistance(Config.PRE_SIZE)// 提前多少数据继续加载。上滑动加载更多,距离最后item还有2个会触发。下滑刷新同理
                    .setInitialLoadSizeHint(Config.INIT_SIZE)// 初始化加载数量
                    .setEnablePlaceholders(false)// 配置是否启动PlaceHolders
                    .build();
        }
        public LiveData<PagedList<Student>> getListLiveData() {
            return listLiveData;
        }
    }
    

    常量类:

    public class Config {
        public static final int PER_PAGE_SIZE = 8;
        public static final int PRE_SIZE = 2;
        public static final int INIT_SIZE = 8;
    }
    

    创建工厂数据源,配置分页信息(每页数据量,初始化数据量等信息)

    定义Adapter

    public class RecyclerPagingAdapter extends PagedListAdapter<Student, RecyclerPagingAdapter.RecyclerViewHolder> {
    
        private static DiffUtil.ItemCallback<Student> DIFF_STUDENT = new DiffUtil.ItemCallback<Student>() {
            @Override
            public boolean areItemsTheSame(@NonNull Student oldItem, @NonNull Student newItem) {
                return oldItem.getId() == newItem.getId();
            }
    
            @Override
            public boolean areContentsTheSame(@NonNull Student oldItem, @NonNull Student newItem) {
                return oldItem.equals(newItem);
            }
        };
    
        public RecyclerPagingAdapter() {
            super(DIFF_STUDENT);
        }
    
        @NonNull
        @Override
        public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_paging, parent, false);
            return new RecyclerViewHolder(view);
        }
    
        @Override
        public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
            // 从数据源中获取对应Data数据,可能为空
            Student student = getItem(position);
            if (student == null) {
                holder.tvId.setText("加载中...");
                holder.tvName.setText("加载中...");
                holder.tvGender.setText("加载中...");
            } else {
                holder.tvId.setText(student.getId());
                holder.tvName.setText(student.getName());
                holder.tvGender.setText(student.getGender());
            }
        }
    
        public static class RecyclerViewHolder extends RecyclerView.ViewHolder {
            TextView tvId;
            TextView tvName;
            TextView tvGender;
    
            public RecyclerViewHolder(@NonNull View itemView) {
                super(itemView);
                tvId = itemView.findViewById(R.id.tvId);
                tvName = itemView.findViewById(R.id.tvName);
                tvGender = itemView.findViewById(R.id.tvGender);
            }
        }
    }
    

    列表页item配置,diff处理用到equals

    显示数据

    public class PagingActivity extends AppCompatActivity {
        private static final String TAG = "-paging-PagingActivity";
        private RecyclerView recyclerView;
        private RecyclerPagingAdapter adapter;
        private StudentViewModel viewModel;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_paging);
            recyclerView = findViewById(R.id.recyclerView);
            adapter = new RecyclerPagingAdapter();
            // 第一次初始化
            refresh();
            recyclerView.setAdapter(adapter);
            recyclerView.setLayoutManager(new LinearLayoutManager(this));
        }
    
        private void refresh(){
            adapter.submitList(null);
            viewModel = new ViewModelProvider(this,new ViewModelProvider.NewInstanceFactory()).get(StudentViewModel.class);
            // 获取数据,监听数据改变
            viewModel.getListLiveData().observe(this, new Observer<PagedList<Student>>() {
                @Override
                public void onChanged(PagedList<Student> students) {
                    Log.d(TAG, "数据源改变-onChanged-size:"+students.size());
                    // 设定新的数据源
                    adapter.submitList(students);
                }
            });
        }
    
        /**
         * 刷新数据源:可以模仿下拉刷新触发点
         * @param view
         */
        public void onRefresh(View view) {
            refresh();
        }
    }
    

    原理

    通过Paging可以做分页处理。
    清除adapter里的数据:submitList()传null值,可以模仿刷新


    image.png

    相关文章

      网友评论

          本文标题:Jetpack学习-7-Paging

          本文链接:https://www.haomeiwen.com/subject/feegdktx.html