真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

怎么使用Jetpackpaging

本篇內(nèi)容主要講解“怎么使用Jetpack paging”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“怎么使用Jetpack paging”吧!

為江西等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及江西網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、江西網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

1. Demo概述

在正式介紹paging 的使用之前,我們先來(lái)看看最終的效果是怎么樣的。

怎么使用Jetpack paging

效果是非常的簡(jiǎn)單,就是有一個(gè)RecyclerView在顯示數(shù)據(jù),然后我們向下滑動(dòng),滑動(dòng)到一定位置,paging會(huì)自動(dòng)請(qǐng)求數(shù)據(jù),這也就是分頁(yè)請(qǐng)求的效果.paging的目的就是實(shí)現(xiàn)分頁(yè)加載,之前我們都是自己實(shí)現(xiàn)分頁(yè),這次是Google爸爸為我們實(shí)現(xiàn)。不得不說(shuō),jetpack真香!

2. 準(zhǔn)備components

要想使用paging,我們得準(zhǔn)備幾個(gè)東西(當(dāng)然,導(dǎo)依賴這種基本操作肯定是必須的,我就不介紹了哈)。

  1. DataSource:顧名思義,數(shù)據(jù)源,獲取數(shù)據(jù)是通過(guò)它實(shí)現(xiàn)的。

  2. PagedList: 數(shù)據(jù)源獲取的數(shù)據(jù)最終靠PagedList來(lái)承載。對(duì)于PagedList,我們可以這樣來(lái)理解,它就是一頁(yè)數(shù)據(jù)的集合。每請(qǐng)求一頁(yè),就是新的一個(gè)PagedList對(duì)象。

  3. PagedListAdapter:這個(gè)Adapter就是一個(gè)RecyclerViewAdapter。不過(guò)我們?cè)谑褂?code>paging實(shí)現(xiàn)RecyclerView的分頁(yè)加載效果,不能直接繼承RecyclerViewAdapter,而是需要繼承PagedListAdapter。

3. 自定義DataSource

說(shuō)實(shí)話,自定義DataSource沒(méi)有什么難度,但是我為什么要單獨(dú)提出來(lái)呢?首先官方文檔上,實(shí)現(xiàn)的是ItemKeyedDataSource,而我這里實(shí)現(xiàn)的是PositionalDataSource。雖然差別不是很大,但是還是有點(diǎn)區(qū)別,因?yàn)樵谶@里我踩過(guò)兩個(gè)坑。我相信,通過(guò)這兩個(gè)坑,以后遇到類似的問(wèn)題,會(huì)找到解決思路。
?在貼代碼之前,我們先來(lái)看看實(shí)現(xiàn)PositionalDataSource需要注意的地方。
?首先,我們得了解一下需要實(shí)現(xiàn)的兩個(gè)方法:

方法名含義
loadInitial加載初始化數(shù)據(jù),可以這么來(lái)理解,加載的是第一頁(yè)的數(shù)據(jù)。形象的說(shuō),當(dāng)我們第一次打開(kāi)頁(yè)面,需要回調(diào)此方法來(lái)獲取數(shù)據(jù)。
loadRange當(dāng)有了初始化數(shù)據(jù)之后,滑動(dòng)的時(shí)候如果需要加載數(shù)據(jù)的話,會(huì)調(diào)用此方法。

現(xiàn)在,我們來(lái)看看最終實(shí)現(xiàn)的代碼。

  public class ConcertDataSource extends PositionalDataSource {
      private final Retrofit mRetrofit = new Retrofit.Builder()
              .baseUrl("http://api.apiopen.top/")
              .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
              .addConverterFactory(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);
      }
  }

然后,我結(jié)合上面的代碼來(lái)介紹一下我踩過(guò)的兩個(gè)坑(其實(shí)這兩個(gè)坑可以歸并為一個(gè)坑,因?yàn)槎际且粋€(gè)原因?qū)е?。
?我先來(lái)描述我之前我遇到的問(wèn)題,在第一次打開(kāi)界面時(shí),我發(fā)現(xiàn),RecyclerView沒(méi)有顯示任何的數(shù)據(jù),同時(shí)經(jīng)過(guò)debug,發(fā)現(xiàn)loadInitial方法被回調(diào)到的,但是最終Adapter里面的itemCount為0。這是什么原因?qū)е碌哪??我們?lái)看看現(xiàn)在的loadInitial方法的實(shí)現(xiàn):

      @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);
      }

我們通過(guò)LoadInitialCallbackonResult方法一共傳遞了三個(gè)參數(shù),這三個(gè)參數(shù)分別表示什么意思?我們先來(lái)LoadInitialCallback這個(gè)類吧。

    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一共有兩個(gè)onResult方法。而我這里出現(xiàn)了RecyclerView不顯示任何數(shù)據(jù),是因?yàn)槲艺{(diào)用得是兩個(gè)參數(shù)的onResult方法,導(dǎo)致了totalCount為0,所以顯示不出任何數(shù)據(jù)。
?第二個(gè)問(wèn)題就是,數(shù)據(jù)顯示出來(lái)了,但是始終顯示一頁(yè)的數(shù)據(jù),也就是說(shuō)loadRange方法不會(huì)調(diào)用。其實(shí)也是totalCount導(dǎo)致的,當(dāng)時(shí)我解決了第一個(gè)的問(wèn)題時(shí),直接給totalCount傳遞的是Listsize(假設(shè)為N條)。也就是說(shuō),PositionalDataSource最終一共只會(huì)獲取N條的數(shù)據(jù),因?yàn)榈谝豁?yè)的大小恰好就等于N,所以不會(huì)調(diào)用loadRange方法去加載更多的數(shù)據(jù)。

3. 創(chuàng)建ViewModel

相信比較熟悉JetPack的同學(xué)都知道,在Jetpack的架構(gòu)里面,推薦每個(gè)頁(yè)面持有一個(gè)ViewModel對(duì)象,以保證數(shù)據(jù)的正確性和避免其他的問(wèn)題。本文就不介紹ViewModel,不太了解的同學(xué)可以看一下的官方文檔,這是鏈接:  ViewModel Overview Part of Android Jetpack。
?之前,我們已經(jīng)成功的自定義一個(gè)DataSource,現(xiàn)在我們來(lái)看看怎么使用ViewModelDataSource連接起來(lái)。
?首先,我們得創(chuàng)建工廠類,用來(lái)創(chuàng)建DataSource對(duì)象,這在Jetpack架構(gòu)里面是基本需要。

  public class ConcertFactory extends DataSource.Factory {
      private MutableLiveData mSourceLiveData =
              new MutableLiveData<>();
      @Override
      public DataSource create() {
          ConcertDataSource concertDataSource = new ConcertDataSource();
          mSourceLiveData.postValue(concertDataSource);
          return concertDataSource;
      }
  }

至于為什么需要一個(gè)MutableLiveDataDataSource包裝一下,這個(gè)我也不是很了解,官方文檔就是這么寫的(可能是讓DataSource監(jiān)聽(tīng)Activity或者Fragment的生命周期,以保證只在頁(yè)面活躍狀態(tài)(onStart或者onResume)獲取數(shù)據(jù))。
?其次,就是創(chuàng)建對(duì)應(yīng)的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

首先,我們來(lái)看一下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時(shí),我們需要注意的是,PagedListAdapter內(nèi)部默認(rèn)實(shí)現(xiàn)DiffUtil來(lái)進(jìn)行數(shù)據(jù)的差量計(jì)算,所以我們?cè)跇?gòu)造方法里面?zhèn)鬟f一個(gè)DiffUtil.ItemCallback。至于DiffUtil是什么,以及它內(nèi)部的算法實(shí)現(xiàn),我們這里就不介紹,有興趣的同學(xué)可以關(guān)注樓主的RecyclerView源碼分析系列文章,在不久的將來(lái),我會(huì)詳細(xì)的分析它的內(nèi)部實(shí)現(xiàn)。
?然后,我們?cè)賮?lái)看看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));
      }
  }

整個(gè)結(jié)構(gòu)就這樣的,是不是非常簡(jiǎn)單?不過(guò),到這里可能有人可能有疑問(wèn),我就實(shí)現(xiàn)了一個(gè)RecyclerView加載更多的數(shù)據(jù),你就讓我定義這么多的類,是不是有點(diǎn)小題大做呢?
?其實(shí)不然,Jetpack是Google官方推薦的一種App架構(gòu)方案,在這種結(jié)構(gòu)下,會(huì)避免很多的問(wèn)題,比如說(shuō)內(nèi)存泄漏和空指針異常等等。之所以使用這種方案來(lái)架構(gòu)App,不是我們吃飽撐的沒(méi)事干,而是為了解決傳統(tǒng)架構(gòu)方案下不能解決的問(wèn)題。當(dāng)然可能還有其他的第三方解決方案,但是肯定不比Jetpack權(quán)威,畢竟Google爸爸親自設(shè)計(jì)的。

到此,相信大家對(duì)“怎么使用Jetpack paging”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


分享名稱:怎么使用Jetpackpaging
當(dāng)前網(wǎng)址:http://weahome.cn/article/jsisoe.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部