基于Android官方Paging Library的RecyclerView分页加载框架


基于Android官方Paging Library的RecyclerView分页加载框架


我之前写了一篇RecyclerView分页加载机制的文章,是基于Android官方的AsyncListUtil实现的,详情见附录文章1。现在再介绍一种RecyclerView分页加载框架:Android Paging Library。
Android Paging Library是Android官方support-v7支持包中专门做的分页框架,详细文档见谷歌官方文档附录2页面。我写这篇文章时候Paging Library的版本是1.0.0-alpha3。
使用Android Paging Library首先需要在gradle添加引用:
  1. implementation ‘android.arch.paging:runtime:1.0.0-alpha3’  
implementation 'android.arch.paging:runtime:1.0.0-alpha3'

下面我写示例代码做一个简单的演示:

  1. package zhangphil.demo;  
  2.   
  3. import android.arch.paging.PagedList;  
  4. import android.arch.paging.PagedListAdapter;  
  5. import android.arch.paging.TiledDataSource;  
  6. import android.graphics.Color;  
  7. import android.support.annotation.NonNull;  
  8. import android.support.v7.app.AppCompatActivity;  
  9. import android.os.Bundle;  
  10. import android.support.v7.recyclerview.extensions.DiffCallback;  
  11. import android.support.v7.widget.LinearLayoutManager;  
  12. import android.support.v7.widget.RecyclerView;  
  13. import android.text.TextUtils;  
  14. import android.util.Log;  
  15. import android.view.LayoutInflater;  
  16. import android.view.View;  
  17. import android.view.ViewGroup;  
  18. import android.widget.LinearLayout;  
  19. import android.widget.TextView;  
  20.   
  21. import java.util.ArrayList;  
  22. import java.util.List;  
  23. import java.util.concurrent.Executor;  
  24.   
  25. public class MainActivity extends AppCompatActivity {  
  26.     private PagedList<DataBean> mPagedList;  
  27.     private MyDataSource mDataSource;  
  28.   
  29.     private RecyclerView mRecyclerView;  
  30.     private PagedListAdapter mAdapter;  
  31.   
  32.     private LinearLayoutManager mLayoutManager;  
  33.   
  34.     @Override  
  35.     protected void onCreate(Bundle savedInstanceState) {  
  36.         super.onCreate(savedInstanceState);  
  37.         setContentView(R.layout.activity_main);  
  38.   
  39.         mDataSource = new MyDataSource();  
  40.         makePageList();  
  41.   
  42.         mRecyclerView = findViewById(R.id.recycler_view);  
  43.   
  44.         mLayoutManager = new LinearLayoutManager(this);  
  45.         mLayoutManager.setOrientation(LinearLayout.VERTICAL);  
  46.         mRecyclerView.setLayoutManager(mLayoutManager);  
  47.   
  48.         mAdapter = new MyAdapter();  
  49.         mRecyclerView.setAdapter(mAdapter);  
  50.   
  51.         mAdapter.setList(mPagedList);  
  52.   
  53.         mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {  
  54.             private int lastPos;  
  55.   
  56.             @Override  
  57.             public void onScrollStateChanged(RecyclerView recyclerView, int newState) {  
  58.                 super.onScrollStateChanged(recyclerView, newState);  
  59.   
  60.                 lastPos = mLayoutManager.findLastVisibleItemPosition();  
  61.   
  62.                 mPagedList.loadAround(lastPos);//触发Android Paging的加载事务逻辑。  
  63.             }  
  64.         });  
  65.     }  
  66.   
  67.     private void makePageList() {  
  68.         PagedList.Config mPagedListConfig = new PagedList.Config.Builder()  
  69.                 .setPageSize(3//分页数据的数量。在后面的DataSource之loadRange中,count即为每次加载的这个设定值。  
  70.                 .setPrefetchDistance(5//初始化时候,预取数据数量。  
  71.                 .setEnablePlaceholders(false)  
  72.                 .build();  
  73.   
  74.         mPagedList = new PagedList.Builder()  
  75.                 .setConfig(mPagedListConfig)  
  76.                 .setDataSource(mDataSource)  
  77.                 .setMainThreadExecutor(new BackgroundThreadTask()) //初始化阶段启用  
  78.                 .setBackgroundThreadExecutor(new MainThreadTask()) //初始化阶段启动  
  79.                 .build();  
  80.     }  
  81.   
  82.     private class BackgroundThreadTask implements Executor {  
  83.         public BackgroundThreadTask() {  
  84.             this.execute(new Runnable() {  
  85.                 @Override  
  86.                 public void run() {  
  87.                     Log.d(”BackgroundThreadTask”“run”);  
  88.                 }  
  89.             });  
  90.         }  
  91.   
  92.         @Override  
  93.         public void execute(@NonNull Runnable runnable) {  
  94.             runnable.run();  
  95.         }  
  96.     }  
  97.   
  98.     private class MainThreadTask implements Executor {  
  99.         public MainThreadTask() {  
  100.             this.execute(new Runnable() {  
  101.                 @Override  
  102.                 public void run() {  
  103.                     Log.d(”MainThreadTask”“run”);  
  104.                 }  
  105.             });  
  106.         }  
  107.   
  108.         @Override  
  109.         public void execute(@NonNull Runnable runnable) {  
  110.             runnable.run();  
  111.         }  
  112.     }  
  113.   
  114.     private class MyDataSource extends TiledDataSource<DataBean> {  
  115.   
  116.         @Override  
  117.         public int countItems() {  
  118.             return TiledDataSource.COUNT_UNDEFINED;  
  119.         }  
  120.   
  121.         / 
  122.           注意,这里需要后台线程化。 
  123.           
  124.           @param startPosition 
  125.           @param count 
  126.           @return 
  127.          /  
  128.         @Override  
  129.         public List<DataBean> loadRange(int startPosition, int count) {  
  130.             Log.d(”MyDataSource”“loadRange:” + startPosition + “,” + count);  
  131.             List<DataBean> list = loadData(startPosition, count);  
  132.             return list;  
  133.         }  
  134.     }  
  135.   
  136.     / 
  137.       假设这里需要做一些后台线程的数据加载任务。 
  138.       
  139.       @param startPosition 
  140.       @param count 
  141.       @return 
  142.      /  
  143.     private List<DataBean> loadData(int startPosition, int count) {  
  144.         List<DataBean> list = new ArrayList();  
  145.   
  146.         for (int i = 0; i < count; i++) {  
  147.             DataBean data = new DataBean();  
  148.             data.id = startPosition + i;  
  149.             data.content = ”zhangphil@” + data.id;  
  150.             list.add(data);  
  151.         }  
  152.   
  153.         return list;  
  154.     }  
  155.   
  156.     private class MyViewHolder extends RecyclerView.ViewHolder {  
  157.         public TextView text1;  
  158.         public TextView text2;  
  159.   
  160.         public MyViewHolder(View itemView) {  
  161.             super(itemView);  
  162.   
  163.             text1 = itemView.findViewById(android.R.id.text1);  
  164.             text1.setTextColor(Color.RED);  
  165.   
  166.             text2 = itemView.findViewById(android.R.id.text2);  
  167.             text2.setTextColor(Color.BLUE);  
  168.         }  
  169.     }  
  170.   
  171.     private class MyAdapter extends PagedListAdapter<DataBean, MyViewHolder> {  
  172.         public MyAdapter() {  
  173.             super(mDiffCallback);  
  174.         }  
  175.   
  176.         @Override  
  177.         public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  
  178.             View view = LayoutInflater.from(getApplicationContext()).inflate(android.R.layout.simple_list_item_2, null);  
  179.             MyViewHolder holder = new MyViewHolder(view);  
  180.             return holder;  
  181.         }  
  182.   
  183.         @Override  
  184.         public void onBindViewHolder(MyViewHolder holder, int position) {  
  185.             DataBean data = mPagedList.get(position);  
  186.             holder.text1.setText(String.valueOf(position));  
  187.             holder.text2.setText(String.valueOf(data.content));  
  188.         }  
  189.     }  
  190.   
  191.     private DiffCallback<DataBean> mDiffCallback = new DiffCallback<DataBean>() {  
  192.   
  193.         @Override  
  194.         public boolean areItemsTheSame(@NonNull DataBean oldItem, @NonNull DataBean newItem) {  
  195.             Log.d(”DiffCallback”“areItemsTheSame”);  
  196.             return oldItem.id == newItem.id;  
  197.         }  
  198.   
  199.         @Override  
  200.         public boolean areContentsTheSame(@NonNull DataBean oldItem, @NonNull DataBean newItem) {  
  201.             Log.d(”DiffCallback”“areContentsTheSame”);  
  202.             return TextUtils.equals(oldItem.content, newItem.content);  
  203.         }  
  204.     };  
  205.   
  206.     private class DataBean {  
  207.         public int id;  
  208.         public String content;  
  209.     }  
  210. }  
package zhangphil.demo;

import android.arch.paging.PagedList;
import android.arch.paging.PagedListAdapter;
import android.arch.paging.TiledDataSource;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.recyclerview.extensions.DiffCallback;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;

public class MainActivity extends AppCompatActivity {
private PagedList<DataBean> mPagedList;
private MyDataSource mDataSource;

private RecyclerView mRecyclerView;
private PagedListAdapter mAdapter;

private LinearLayoutManager mLayoutManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mDataSource = new MyDataSource();
    makePageList();

    mRecyclerView = findViewById(R.id.recycler_view);

    mLayoutManager = new LinearLayoutManager(this);
    mLayoutManager.setOrientation(LinearLayout.VERTICAL);
    mRecyclerView.setLayoutManager(mLayoutManager);

    mAdapter = new MyAdapter();
    mRecyclerView.setAdapter(mAdapter);

    mAdapter.setList(mPagedList);

    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        private int lastPos;

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);

            lastPos = mLayoutManager.findLastVisibleItemPosition();

            mPagedList.loadAround(lastPos);//触发Android Paging的加载事务逻辑。
        }
    });
}

private void makePageList() {
    PagedList.Config mPagedListConfig = new PagedList.Config.Builder()
            .setPageSize(3) //分页数据的数量。在后面的DataSource之loadRange中,count即为每次加载的这个设定值。
            .setPrefetchDistance(5) //初始化时候,预取数据数量。
            .setEnablePlaceholders(false)
            .build();

    mPagedList = new PagedList.Builder()
            .setConfig(mPagedListConfig)
            .setDataSource(mDataSource)
            .setMainThreadExecutor(new BackgroundThreadTask()) //初始化阶段启用
            .setBackgroundThreadExecutor(new MainThreadTask()) //初始化阶段启动
            .build();
}

private class BackgroundThreadTask implements Executor {
    public BackgroundThreadTask() {
        this.execute(new Runnable() {
            @Override
            public void run() {
                Log.d("BackgroundThreadTask", "run");
            }
        });
    }

    @Override
    public void execute(@NonNull Runnable runnable) {
        runnable.run();
    }
}

private class MainThreadTask implements Executor {
    public MainThreadTask() {
        this.execute(new Runnable() {
            @Override
            public void run() {
                Log.d("MainThreadTask", "run");
            }
        });
    }

    @Override
    public void execute(@NonNull Runnable runnable) {
        runnable.run();
    }
}

private class MyDataSource extends TiledDataSource&lt;DataBean&gt; {

    @Override
    public int countItems() {
        return TiledDataSource.COUNT_UNDEFINED;
    }

    /**
     * 注意,这里需要后台线程化。
     *
     * @param startPosition
     * @param count
     * @return
     */
    @Override
    public List&lt;DataBean&gt; loadRange(int startPosition, int count) {
        Log.d("MyDataSource", "loadRange:" + startPosition + "," + count);
        List&lt;DataBean&gt; list = loadData(startPosition, count);
        return list;
    }
}

/**
 * 假设这里需要做一些后台线程的数据加载任务。
 *
 * @param startPosition
 * @param count
 * @return
 */
private List&lt;DataBean&gt; loadData(int startPosition, int count) {
    List&lt;DataBean&gt; list = new ArrayList();

    for (int i = 0; i &lt; count; i++) {
        DataBean data = new DataBean();
        data.id = startPosition + i;
        data.content = "zhangphil@" + data.id;
        list.add(data);
    }

    return list;
}

private class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView text1;
    public TextView text2;

    public MyViewHolder(View itemView) {
        super(itemView);

        text1 = itemView.findViewById(android.R.id.text1);
        text1.setTextColor(Color.RED);

        text2 = itemView.findViewById(android.R.id.text2);
        text2.setTextColor(Color.BLUE);
    }
}

private class MyAdapter extends PagedListAdapter&lt;DataBean, MyViewHolder&gt; {
    public MyAdapter() {
        super(mDiffCallback);
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(getApplicationContext()).inflate(android.R.layout.simple_list_item_2, null);
        MyViewHolder holder = new MyViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        DataBean data = mPagedList.get(position);
        holder.text1.setText(String.valueOf(position));
        holder.text2.setText(String.valueOf(data.content));
    }
}

private DiffCallback&lt;DataBean&gt; mDiffCallback = new DiffCallback&lt;DataBean&gt;() {

    @Override
    public boolean areItemsTheSame(@NonNull DataBean oldItem, @NonNull DataBean newItem) {
        Log.d("DiffCallback", "areItemsTheSame");
        return oldItem.id == newItem.id;
    }

    @Override
    public boolean areContentsTheSame(@NonNull DataBean oldItem, @NonNull DataBean newItem) {
        Log.d("DiffCallback", "areContentsTheSame");
        return TextUtils.equals(oldItem.content, newItem.content);
    }
};

private class DataBean {
    public int id;
    public String content;
}

}

代码实现的功能很简单,当RecyclerView不断下滑时,就触发分页加载,把RecyclerView后续使用的数据分页加载显示出来。暂时我将现阶段对Android Paging Library技术的心得记录下来,作为我学习Android Paging Library技术的阶段性备忘录。这部分代码还有待进一步完善,Android Paging Library技术细节后续会继续跟进研究。


附录:
1,《基于Android官方AsyncListUtil优化改进RecyclerView分页加载机制(一)》链接: http://blog.csdn.net/zhangphil/article/details/78603499&nbsp;
2,谷歌Android官方Android Paging Library技术文档主页: https://developer.android.google.cn/topic/libraries/architecture/paging.html#classes

转自: http://blog.csdn.net/zhangphil/article/details/78627332
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值