基于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添加引用:

implementation 'android.arch.paging:runtime:1.0.0-alpha3'

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

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<DataBean> { 
 
        @Override 
        public int countItems() { 
            return TiledDataSource.COUNT_UNDEFINED; 
        } 
 
        /** 
         * 注意,这里需要后台线程化。 
         * 
         * @param startPosition 
         * @param count 
         * @return 
         */ 
        @Override 
        public List<DataBean> loadRange(int startPosition, int count) { 
            Log.d("MyDataSource", "loadRange:" + startPosition + "," + count); 
            List<DataBean> list = loadData(startPosition, count); 
            return list; 
        } 
    } 
 
    /** 
     * 假设这里需要做一些后台线程的数据加载任务。 
     * 
     * @param startPosition 
     * @param count 
     * @return 
     */ 
    private List<DataBean> loadData(int startPosition, int count) { 
        List<DataBean> list = new ArrayList(); 
 
        for (int i = 0; i < 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<DataBean, MyViewHolder> { 
        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<DataBean> mDiffCallback = new DiffCallback<DataBean>() { 
 
        @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 
2,谷歌Android官方Android Paging Library技术文档主页:https://developer.android.google.cn/topic/libraries/architecture/paging.html#classes

发布评论

分享到:

IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

基于Android官方AsyncListUtil优化经典ListView分页加载机制(二)详解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。