In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "how to use Jetpack paging". Interested friends may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Now let the editor take you to learn how to use Jetpack paging.
1. Overview of Demo
Before formally introducing the use of paging, let's take a look at what the end result looks like.
The effect is very simple, that is, there is a RecyclerView displaying data, and then we slide down and slide to a certain position, and paging will automatically request data, which is the effect of paging request. The purpose of paging is to achieve paging loading. Before, we all implemented paging by ourselves, this time by Google dad. I have to say, jetpack smells so good!
two。 Prepare components
To use paging, we need to prepare a few things (of course, the basic operation of guiding dependency is certainly necessary, so I won't introduce it).
DataSource: as the name implies, data source, access to data is achieved through it.
PagedList: the data obtained by the data source is ultimately carried by PagedList. For PagedList, we can understand it this way, it is a collection of one page of data. Each page requested is a new PagedList object.
PagedListAdapter: this Adapter is an Adapter of RecyclerView. However, we are using paging to achieve the paging loading effect of RecyclerView, so we can not directly inherit RecyclerView's Adapter, but need to inherit PagedListAdapter.
3. Custom DataSource
To be honest, it's not difficult to customize DataSource, but why should I mention it separately? First of all, in the official documentation, the implementation is ItemKeyedDataSource, while what I am implementing here is PositionalDataSource. Although the difference is not very big, it is still a little different, because I have stepped on two pits here. I believe that through these two pits, if we encounter similar problems in the future, we will find a solution.
Before pastes the code, let's take a look at what we need to pay attention to when implementing PositionalDataSource.
first, we need to look at two methods that need to be implemented:
The method name means that loadInitial loads the initialization data, which is, to put it this way, the data from the first page. Figuratively speaking, when we open the page for the first time, we need to call back this method to get the data. LoadRange calls this method if it needs to load data when it slides after it has initialized data.
Now, let's take a look at the code that is finally implemented.
Public class ConcertDataSource extends PositionalDataSource {private final Retrofit mRetrofit = new Retrofit.Builder () .baseUrl ("http://api.apiopen.top/") .addCallAdapterFactory (RxJava2CallAdapterFactory.create ()) .addC onverterFactory (GsonConverterFactory.create ()) .build (); private final Service mService; public ConcertDataSource () {mService = mRetrofit.create (Service.class)) } @ Override public void loadInitial (@ NonNull LoadInitialParams params, @ NonNull final LoadInitialCallback callback) {/ / fetchItem (0, params.pageSize, new Callback () {/ / @ Override / / public void onResult (Bean value) {/ / callback.onResult (value.getResult (), 0, 2000); / /} /}) Callback.onResult (fetchItems (0,20), 0, 2000);} @ Override public void loadRange (@ NonNull LoadRangeParams params, @ NonNull final LoadRangeCallback callback) {/ / fetchItem (params.startPosition, params.loadSize, new Callback () {/ / @ Override / / public void onResult (Bean value) {/ / callback.onResult (value.getResult ()) / /} / /}); callback.onResult (fetchItems (params.startPosition, params.loadSize));} private List fetchItems (int startPosition, int pageSize) {List list = new ArrayList (); for (int I = startPosition; I
< startPosition + pageSize; i++) { Concert concert = new Concert(); concert.setAuthor("author = " + i); concert.setContent("content = " + i); concert.setTitle("title = " + i); list.add(concert); } return list; } private void fetchItem(final int startPosition, int size, final Callback callback) { mService.getCall(startPosition, size).subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(Bean value) { callback.onResult(value); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } }); } private interface Callback { void onResult(Bean value); } } 然后,我结合上面的代码来介绍一下我踩过的两个坑(其实这两个坑可以归并为一个坑,因为都是一个原因导致)。 我先来描述我之前我遇到的问题,在第一次打开界面时,我发现,RecyclerView没有显示任何的数据,同时经过debug,发现loadInitial方法被回调到的,但是最终Adapter里面的itemCount为0。这是什么原因导致的呢?我们来看看现在的loadInitial方法的实现: @Override public void loadInitial(@NonNull LoadInitialParams params, @NonNull final LoadInitialCallback callback) { // fetchItem(0, params.pageSize, new Callback() { // @Override // public void onResult(Bean value) { // callback.onResult(value.getResult(), 0, 2000); // } // }); callback.onResult(fetchItems(0, 20), 0, 2000); } 我们通过LoadInitialCallback的onResult方法一共传递了三个参数,这三个参数分别表示什么意思?我们先来LoadInitialCallback这个类吧。 public abstract static class LoadInitialCallback { public abstract void onResult(@NonNull List data, int position, int totalCount); public abstract void onResult(@NonNull List data, int position); } LoadInitialCallback一共有两个onResult方法。而我这里出现了RecyclerView不显示任何数据,是因为我调用得是两个参数的onResult方法,导致了totalCount为0,所以显示不出任何数据。 第二个问题就是,数据显示出来了,但是始终显示一页的数据,也就是说loadRange方法不会调用。其实也是totalCount导致的,当时我解决了第一个的问题时,直接给totalCount传递的是List的size(假设为N条)。也就是说,PositionalDataSource最终一共只会获取N条的数据,因为第一页的大小恰好就等于N,所以不会调用loadRange方法去加载更多的数据。 3. 创建ViewModel 相信比较熟悉JetPack的同学都知道,在Jetpack的架构里面,推荐每个页面持有一个ViewModel对象,以保证数据的正确性和避免其他的问题。本文就不介绍ViewModel,不太了解的同学可以看一下的官方文档,这是链接: ViewModel Overview Part of Android Jetpack。 之前,我们已经成功的自定义一个DataSource,现在我们来看看怎么使用ViewModel跟DataSource连接起来。 首先,我们得创建工厂类,用来创建DataSource对象,这在Jetpack架构里面是基本需要。 public class ConcertFactory extends DataSource.Factory { private MutableLiveData mSourceLiveData = new MutableLiveData(); @Override public DataSource create() { ConcertDataSource concertDataSource = new ConcertDataSource(); mSourceLiveData.postValue(concertDataSource); return concertDataSource; } } 至于为什么需要一个MutableLiveData将DataSource包装一下,这个我也不是很了解,官方文档就是这么写的(可能是让DataSource监听Activity或者Fragment的生命周期,以保证只在页面活跃状态(onStart或者onResume)获取数据)。 其次,就是创建对应的ViewModel: public class ConcertViewModel extends ViewModel { private final LiveData convertList; private DataSource concertDataSource; public ConcertViewModel() { ConcertFactory concertFactory = new ConcertFactory(); concertDataSource = concertFactory.create(); convertList = new LivePagedListBuilder(concertFactory, 20).build(); } public void invalidateDataSource() { concertDataSource.invalidate(); } public LiveData getConvertList() { return convertList; } }4. RecyclerView 首先,我们来看一下Adapter的定义: public class RecyclerAdapter extends PagedListAdapter { protected RecyclerAdapter() { super(DIFF_CALLBACK); } @NonNull @Override public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recyclerview, parent, false); return new RecyclerViewHolder(view); } @Override public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) { Concert concert = getItem(position); if (concert != null) { holder.mTitleTextView.setText(concert.getTitle()); holder.mAuthorTextView.setText(concert.getAuthor()); holder.mContentTextView.setText(concert.getContent()); } } public static class RecyclerViewHolder extends RecyclerView.ViewHolder { TextView mTitleTextView; TextView mAuthorTextView; TextView mContentTextView; public RecyclerViewHolder(View itemView) { super(itemView); mTitleTextView = itemView.findViewById(R.id.title); mAuthorTextView = itemView.findViewById(R.id.author); mContentTextView = itemView.findViewById(R.id.content); } } private static DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() { @Override public boolean areItemsTheSame(Concert oldConcert, Concert newConcert) { return oldConcert.getTitle().equals(newConcert.getTitle()); } @Override public boolean areContentsTheSame(Concert oldConcert, Concert newConcert) { return oldConcert.equals(newConcert); } }; } 在使用PagedListAdapter时,我们需要注意的是,PagedListAdapter内部默认实现DiffUtil来进行数据的差量计算,所以我们在构造方法里面传递一个DiffUtil.ItemCallback。至于DiffUtil是什么,以及它内部的算法实现,我们这里就不介绍,有兴趣的同学可以关注楼主的RecyclerView源码分析系列文章,在不久的将来,我会详细的分析它的内部实现。 然后,我们再来看看Activity里面是怎么使用的: public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private RecyclerAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRecyclerView = findViewById(R.id.recyclerView); adapter = new RecyclerAdapter(); ConcertViewModel viewModel = ViewModelProviders.of(this).get(ConcertViewModel.class); viewModel.getConvertList().observe(this, concerts ->Adapter.submitList (concerts)); mRecyclerView.setAdapter (adapter); mRecyclerView.setLayoutManager (new LinearLayoutManager (this, LinearLayoutManager.VERTICAL, false)); mRecyclerView.addItemDecoration (new SimpleDividerDecoration (this));}}
The whole structure is like this, isn't it very simple? However, some people may have doubts here, I just implemented a RecyclerView to load more data, isn't it a bit of a mountain out of a molehill to let me define so many classes?
is not the case. Jetpack is an App architecture scheme officially recommended by Google. Under this structure, many problems can be avoided, such as memory leaks and null pointer exceptions. The reason why we use this solution to build App is not that we have nothing to do with enough to eat, but to solve the problems that cannot be solved under the traditional architecture. Of course, there may be other third-party solutions, but certainly no more authoritative than Jetpack, after all, Google's father designed it himself.
At this point, I believe you have a deeper understanding of "how to use Jetpack paging". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.