(Java實現)使用官方Paging3分頁庫實現RecyclerView加載更多(loadmore)的功能


Paging是google官方推出的一個分頁加載庫,配合RecyclerView可以很方便實現RecyelerView的Footer和Header,
Paging3相對以前的版本,實現loadmore的功能更為方便,但因為找了一圈,連Google,stackoverflow,github這些地方也找了一遍,都沒有找到關於Paging3的關於java實現代碼
,因此自己就根據一些案例,參考了Google遷移到Paging3的說明,實現了最基本的分頁加載的功能.Footer和Header的實現有時間可能會寫一下.
因為網上也有了一些關於Paging3的教程以及說明.所以這里就不再啰嗦,具體就自己查閱相關資料.

2020.12.21更新:已上傳項目至github
項目地址:https://github.com/1831553190/paging3

正文:

使用Paging3,我們可以很方便的做出加載更多的功能,只要滑動到特定的位置就可以自動加載下一頁的內容.
Paging3的功能實現,可以使用使用Rxjava或者LiveData,本教程使用的是LiveData來實現;

現在的Paging3已經更新到了alpha07版,因此我們引入Paging庫

    implementation "androidx.paging:paging-runtime:3.0.0-alpha07"
    implementation "androidx.paging:paging-guava:3.0.0-alpha07"      //LiveData

以及

    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'  //這里用到了ViewModelKt,所以需要引入,具體是什么玩意請自行搜索,這里不說明

PagingSource:(負責每一分頁的數據加載)

Data就是一個普通的實體類

class Data{
      String title;
      String coverImage;

      public String getCoverImage(){
            return coverImage;
      }
      public void setCoverImage(){
            this.coverImage=coverImage;
      }

      public String getTitle(){
            return title;
      }
      public void setTitle(){
            this.title=title;
      }

}


public class LiveDataSource extends ListenableFuturePagingSource<Integer, Data> {
	//需要用到線程池
	private ListeningExecutorService executorService=MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
        String query;
        public LiveDataSource(String query){
            this.query=query;//查詢內容所需參數
        }

	@NotNull
	@Override
	public ListenableFuture<LoadResult<Integer, Data>> loadFuture(@NotNull LoadParams<Integer> params) {
		Integer nextPageNumber = params.getKey();
		if (nextPageNumber == null) {
			nextPageNumber = 0;//從第0頁開始加載
		}
		Integer finalNextPageNumber = nextPageNumber;
		ListenableFuture<LoadResult<Integer, Data>> pageFuture =Futures
				.transform(executorService.submit(new Callable<List<Data>>() {
			@Override
			public List<Data> call() throws Exception {
				//這里處理耗時操作,比如網絡請求數據,數據庫數據加載
				NetInterface netInterface = NetWorkUtils.getRetrofit().create(NetInterface.class);
				Response<Msg<PageInfo>> infos = netInterface.getPageInfo(finalNextPageNumber,query).execute();
                                //這里用Roterfit請求網絡數據,使用頁數和構造函數傳過來的參數作為請求參數來請求數據
				return infos.body().getData().getList();//得到數據后返回
			}
		}), new Function<List<Data>, LoadResult.Page<Integer, Data>>() {
			@NotNull
			@Override
			public LoadResult.Page<Integer, Data> apply(@Nullable List<Data> input) {
//				這里傳入的三個參數中,剛才請求的數據,第二個參數為請求的上一頁的頁數,當為null時不再加載上一頁,第三個參數則是下一頁,后兩個參數不介紹,自行了解
				return new LoadResult.Page<>(input,finalNextPageNumber==0?null:finalNextPageNumber-1,input.isEmpty()?null:finalNextPageNumber+1);
			}
		}, executorService);

		ListenableFuture<LoadResult<Integer,Data>> partialLoadResultFuture = Futures.catching(
				pageFuture, Exception.class,
				LoadResult.Error::new, executorService);

		return Futures.catching(partialLoadResultFuture,
				Exception.class, LoadResult.Error::new, executorService);
	}
}


ViewModel:(數據更新觀察)

public class LoadMoreViewModel extends ViewModel {
	MutableLiveData<PagingData<Data>> dataMutableLiveData=new MutableLiveData<>();
	PagingConfig pagingConfig=new PagingConfig(10,10,false,10);//初始化配置,可以定義最大加載的數據量

	public LiveData<PagingData<Data>> getPaging(){
		CoroutineScope viewmodelScope= ViewModelKt.getViewModelScope(this);
		Pager<Integer, Data> pager = new Pager<Integer, Data>(pagingConfig, ()->new LiveDataSource("queryId"));構造函數根據自己的需要來調整
		return PagingLiveData.cachedIn(PagingLiveData.getLiveData(pager),viewmodelScope);
	}
}

UI則觀察數據的更新,並加載數據

UI:(Fragment或者Activity),可以在onCreate()或者onCreateView()里面寫

		listAdapter =new ListAdapter(new DiffUtil.ItemCallback<Data>() {
			@Override
			public boolean areItemsTheSame(@NonNull Data oldItem, @NonNull Data newItem) {
				return oldItem.getId()==newItem.getId();
			}

			@Override
			public boolean areContentsTheSame(@NonNull Data oldItem, @NonNull Data newItem) {
				return oldItem.getTitle().equals(newItem.getTitle());
			}
		});
		recyclerView.setAdapter(listAdapter);
		LoadMoreViewModel loadMoreViewModel=new ViewModelProvider(this).get(LoadMoreViewModel.class);
		loadMoreViewModel.getPaging().observe(getViewLifecycleOwner(),
				dataInfoPagingData -> listAdapter.submitData(getLifecycle(),dataInfoPagingData));//觀察數據的更新

Adapter:(基本和原來一樣,但是繼承的類不一樣了)


public class ListAdapter extends PagingDataAdapter<Data, ListAdapter.Holder> {


	public ListAdapter(@NotNull DiffUtil.ItemCallback<Data> diffCallback) {
		super(diffCallback);
	}


	@NonNull
	@Override
	public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
		return new Holder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_info,parent,false));
	}

	@Override
	public void onBindViewHolder(@NonNull Holder holder, int position) {
		holder.title.setText(getItem(position).getTitle());
		Glide.with(holder.itemView.getContext())
				.load(getItem(position).getCoverImage())
				.crossFade()
				.error(R.mipmap.img)
				.into(holder.cover);
		
	}

	class Holder extends RecyclerView.ViewHolder{
		TextView title;
		ImageView cover;
		public Holder(@NonNull View itemView) {
			super(itemView);
			title=itemView.findViewById(R.id.text_title);
			cover=itemView.findViewById(R.id.img_coverPicture);
		}
	}
}

需要寫的代碼基本就這么多

gif暫時沒有,代碼中也用到了一部分lambda表達式(為了簡化一點代碼)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM