写点什么

第五章:paging 使用

用户头像
Android架构
关注
发布于: 10 小时前

public abstract PagedListAdapter getAdapter();


}


  • 创建 ViewModel 处理类


package com.paging.study.viewmodel;


import android.annotation.SuppressLint;


import android.app.Application;


import android.util.ArrayMap;


import android.util.Log;


import androidx.annotation.NonNull;


import androidx.arch.core.executor.ArchTaskExecutor;


import androidx.paging.DataSource;


import androidx.paging.ItemKeyedDataSource;


import com.paging.study.bean.Teacher;


import com.paging.study.http.PagingHttpCallback;


import com.paging.study.http.PagingHttpClient;


import java.util.Collections;


import java.util.Map;


import java.util.concurrent.atomic.AtomicBoolean;


public class BlankViewModel extends AbsViewModel<Teacher.RecordsBean> {


public BlankViewModel(@NonNull Application application) {


super(application);


}


/**


  • 同步位置标记,防止 paging 和我们自己的分页重复


*/


private AtomicBoolean loadAfter = new AtomicBoolean();


@Override


protected DataSource createDataSource() {


return new TeacherDataSource();


}


/**


  • DataSource<Key,Value>数据源:

  • key 对应加载数据的条件信息,value 对应数据实体类

  • <p>

  • PageKeyedDataSource<Key,Value>:

  • 适用于目标数据根据页面信息请求数据的场景

  • <p>

  • ItemKeyedDataSource<Key,Value>:

  • 适用于目标数据的加载依赖特定 item 的信息

  • <p>

  • PositionalDataSource<Key,Value>:

  • 适用于目标数据总数固定,通过特定的位置加载数据


*/


class TeacherDataSource extends ItemKeyedDataSource<String, Teacher.RecordsBean> {


@Override


public void loadInitial(@NonNull LoadInitialParams<String> params,


@NonNull LoadInitialCallback<Teacher.RecordsBean> callback) {


pageCurrent = 1;


//加载初始化数据的


loadData("0", callback);


}


@Override


public void loadAfter(@NonNull LoadParams<String> params, @NonNull LoadCallback<Teacher.RecordsBean> callback) {


//向后加载分页数据的


loadData(params.key, callback);


}


@Override


public void loadBefore(@NonNull LoadParams<String> params, @NonNull LoadCallback<Teacher.RecordsBean> callback) {


callback.onResult(Collections.<Teacher.RecordsBean>emptyList());


//能够向前加载数据的(例如初始化进入加载的是第 3 页,向上翻的时候加载第二第一页)


}


@NonNull


@Override


public String getKey(@NonNull Teacher.RecordsBean item) {


//通过最后一条 item 的信息加载数据


return item.getPaintingId();


}


}


/**


  • 进行网络请求

  • @param key

  • @param callback


*/


private void loadData(String key, ItemKeyedDataSource.LoadCallback<Teacher.RecordsBean> callback) {


if (!key.equals("0")) {


loadAfter.set(true);


}


/**


  • 当前线程为子线程

  • 这里有坑,一定要使用同步请求,因为方法执行完毕是,监听者就收到监听


*/


Map<String, Object> map = new ArrayMap<>();


map.put("searchContent", "");


map.put("size", config.pageSize);


map.put("current", pageCurrent);


PagingHttpClient.getInstance()


.get("home/paintingList", map, new PagingHttpCallback<Teacher>() {


@Override


protected void onNext(Teacher data) {


//标记分页页数


if (data.getRecords() != null && data.getRecords().size() > 0) {


pageCurrent = data.getCurrent() + 1;


}


callback.onResult(data.getRecords());


if (!key.equals("0")) {


//通过 LiveData 发送数据,告诉 UI 层 是否应该主动关闭上拉加载分页的动画


getBoundaryPageData().postValue(data.getRecords().size() > 0);


loadAfter.set(false);


}


Log.e("TTT", "data===>" + data.toString());


}


@Override


protected void onFail(int code, String message) {


}


});


}


/**


  • 自己处理分页

  • @param id

  • @param callback


*/


@SuppressLint("RestrictedApi")


public void loadAfter(String id, ItemKeyedDataSource.LoadCallback<Teacher.RecordsBean> callback) {


if (loadAfter.get()) {


callback.onResult(Collections.emptyList());


return;


}


ArchTaskExecutor.getIOThreadExecutor().execute(new Runnable() {


@Override


public void run() {


loadData(id, callback);


}


});


}


}


  • adapter 适配器(注意 JavaBean 一定要重写 equals 方法)


package com.paging.study.adapter;


import android.content.Context;


import android.view.LayoutInflater;


import android.view.View;


import android.view.ViewGroup;


import android.widget.Toast;


import androidx.annotation.NonNull;


import androidx.paging.PagedListAdapter;


import androidx.recyclerview.widget.DiffUtil;


import androidx.recyclerview.widget.RecyclerView;


import com.paging.study.bean.Teacher;


import cn.yumakeji.jetpackroomstudy.databinding.LayoutTeacherTypeBinding;


import cn.yumakeji.lib_common.global.AppGlobals;


public class HomeAdapter extends PagedListAdapter<Teacher.RecordsBean, HomeAdapter.ViewHolder> {


protected Context mContext;


public HomeAdapter(Context context) {


super(new DiffUtil.ItemCallback<Teacher.RecordsBean>() {


@Override


public boolean areItemsTheSame(@NonNull Teacher.RecordsBean oldItem, @NonNull Teacher.RecordsBean newItem) {


//判断 item 是否相等(这里根据 id 来判断)


return oldItem.getPaintingId() == newItem.getPaintingId();


}


@Override


public boolean areContentsTheSame(@NonNull Teacher.RecordsBean oldItem, @NonNull Teacher.RecordsBean newItem) {


//判断内容是否相等(重写 equals 方法)


return oldItem.equals(newItem);


}


});


this.mContext = context;


}


@NonNull


@Override


public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {


LayoutTeacherTypeBinding binding = LayoutTeacherTypeBinding.inflate(LayoutInflater.from(mContext), parent, false);


return new ViewHolder(binding.getRoot(), binding);


}


@Override


public void onBindViewHolder(@NonNull ViewHolder holder, int position) {


holder.binData(getItem(position));


holder.itemView.setOnClickListener(v -> {


Toast.makeText(AppGlobals.getApplication(), getItem(position).getPaintingName(), Toast.LENGTH_LONG).show();


});


}


public class ViewHolder extends RecyclerView.ViewHolder {


private LayoutTeacherTypeBinding mBinding;


public ViewHolder(@NonNull View itemView, LayoutTeacherTypeBinding binding) {


super(itemView);


this.mBinding = binding;


}


public void binData(Teacher.RecordsBean item) {


mBinding.setItem(item);


}


}


}


适配器布局


<?xml version="1.0" encoding="utf-8"?>


<layout xmlns:android="http://schemas.android.com/apk/res/android"


xmlns:tools="http://schemas.android.com/tools">


<LinearLayout


android:id="@+id/ll_item"


android:layout_width="match_parent"


android:layout_height="wrap_content"


android:orientation="vertical"


android:paddingTop="20dp"


android:paddingBottom="20dp">


<TextView


android:layout_width="match_parent"


android:layout_height="wrap_content"


android:padding="20dp"


android:text="@{item.paintingName}"


android:textSize="24dp"


tools:text="名称" />


<View


android:layout_width="match_parent"


android:layout_height="1dp"


android:background="#eee" />


</LinearLayout>


<data>


<variable


name="item"


type="com.paging.study.bean.Teacher.RecordsBean" />


</data>


</layout>


  • 主页面处理


import android.os.Bundle;


import android.view.LayoutInflater;


import android.view.ViewGroup;


import androidx.annotation.NonNull;


import androidx.paging.ItemKeyedDataSource;


import androidx.paging.PagedList;


import androidx.paging.PagedListAdapter;


import com.paging.study.AbsListFragment;


import com.paging.study.adapter.HomeAdapter;


import com.paging.study.bean.Teacher;


import com.paging.study.datasource.MutablePageKeyedDataSource;


import com.paging.study.viewmodel.BlankViewModel;


import com.scwang.smartrefresh.layout.api.RefreshLayout;


import java.util.List;


public class BlankFragment extends AbsListFragment<Teacher.RecordsBean, BlankViewModel> {


public static BlankFragment newInstance() {


return new BlankFragment();


}


@Override


protected void onCreateViewFrame(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {


}


@Override


public PagedListAdapter getAdapter() {


//return new HomeAdapter(mContext);


return new HomeAdapter(mContext) {


@Override


public void onViewAttachedToWindow(@NonNull ViewHolder holder) {


super.onViewAttachedToWindow(holder);


//进入当前页面,看见了


Log.e("TTT", "onViewAttachedToWindow===>" + holder.getLayoutPosition());


}


@Override


public void onViewDetachedFromWindow(@NonNull ViewHolder holder) {


super.onViewDetachedFromWindow(holder);


//离开当前页面,看不见了


Log.e("TTT", "onViewDetachedFromWindow===>" + holder.getLayoutPosition());


}


@Override


public void onCurrentListChanged(@Nullable PagedList<Teacher.RecordsBean> previousList, @Nullable PagedList<Teacher.RecordsBean> currentList) {


super.onCurrentListChanged(previousList, currentList);


//这个方法是在我们每提交一次 pagelist 对象到 adapter 就会触发一次


//每调用一次 adpater.submitlist


//防止下拉刷新新加 item 显示不出来


if (previousList != null && currentList != null) {


if (!currentList.containsAll(previousList)) {


mRecyclerView.scrollToPosition(0);


}


}


}


};


}


/**


  • paging 只要有一次返回味空,就停止分页了,要手动处理

  • @param refreshLayout


*/


@Override


public void onLoadMore(@NonNull RefreshLayout refreshLayout) {


PagedList<Teacher.RecordsBean> currentList = adapter.getCurrentList();


if (currentList == null || currentList.size() <= 0) {


finishRefresh(false);


return;


}


Teacher.RecordsBean bean = adapter.getCurrentList().get(adapter.getItemCount() - 1);


mViewModel.loadAfter(bean.getPaintingId(), new ItemKeyedDataSource.LoadCallback<Teacher.RecordsBean>() {


@Override


public void onResult(@NonNull List<Teacher.RecordsBean> data) {


PagedList.Config config = currentList.getConfig();


if (data != null && data.size() > 0) {


//这里 咱们手动接管 分页数据加载的时候 使用 MutableItemKeyedDataSource 也是可以的。


//由于当且仅当 paging 不再帮我们分页的时候,我们才会接管。所以 就不需要 ViewModel 中创建的 DataSource 继续工作了,所以使用


//这里主要是将 list 集合转化为 PagedList,给 paging 使用,具体实现抄袭源码


MutablePageKeyedDataSource<Teacher.RecordsBean> dataSource = new MutablePageKeyedDataSource<>();


//这里要把列表上已经显示的先添加到 dataSource.data 中


//而后把本次分页回来的数据再添加到 dataSource.data 中


dataSource.data.addAll(currentList);


dataSource.data.addAll(data);


PagedList<Teacher.RecordsBean> pagedList = dataSource.buildNewPagedList(config);


submitList(pagedList);


}


}


});


}


@Override


public void onRefresh(@NonNull RefreshLayout refreshLayout) {


//invalidate 之后 Paging 会重新创建一个 DataSource 重新调用它的 loadInitial 方法加载初始化数据


//详情见:LivePagedListBuilder#compute 方法


mViewModel.getDataSource().invalidate();


}


}



网络请求封装(注意 paging 的不同)

  • 引入


可单独引入 okhttp


//retrofit:okhttp 封装的网络库


api 'com.squareup.retrofit2:retrofit:2.9.0'


api 'com.squareup.retrofit2:converter-gson:2.9.0'


api 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'


api "com.squareup.okhttp3:logging-interceptor:4.7.2"


  • PagingHttpClient 网络请求核心类


package com.paging.study.http;


import android.util.Log;


import com.yumakeji.rxjava.network.interceptor.CacheIntercepter;


import com.yumakeji.rxjava.network.interceptor.HeaderInterceptor;


import com.yumakeji.rxjava.network.uitils.manager.TrustAllCerts;


import org.jetbrains.annotations.NotNull;


import java.io.File;


import java.io.IOException;


import java.net.FileNameMap;


import java.net.Proxy;


import java.net.URLConnection;


import java.util.List;


import java.util.Map;


import java.util.concurrent.TimeUnit;


import cn.yumakeji.lib_common.BuildConfig;


import cn.yumakeji.lib_common.global.AppGlobals;


import okhttp3.Cache;


import okhttp3.Call;


import okhttp3.MediaType;


import okhttp3.MultipartBody;


import okhttp3.OkHttpClient;


import okhttp3.Request;


import okhttp3.RequestBody;


import okhttp3.Response;


import okhttp3.ResponseBody;


import okhttp3.logging.HttpLoggingInterceptor;


public class PagingHttpClient {


protected OkHttpClient okHttpClient;


protected String sBaseUrl = "https://www.xianghua.art/applets/";


public static PagingHttpClient getInstance() {


return SingletonHolder.sInstance;


}


//静态内部类


private static class SingletonHolder {


private static final PagingHttpClient sInstance = new PagingHttpClient();


}


private PagingHttpClient() {


//缓存地址


File cacheFile = new File(AppGlobals.g


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


etApplication().getExternalCacheDir(), "Http_Cache");


Cache cache = new Cache(cacheFile, 1024 * 1024 * 50); //大小 50Mb


OkHttpClient.Builder builder = new OkHttpClient


.Builder()


.connectTimeout(15, TimeUnit.SECONDS)


.writeTimeout(20, TimeUnit.SECONDS)


.readTimeout(20, TimeUnit.SECONDS)


.pingInterval(20, TimeUnit.SECONDS)


.proxy(Proxy.NO_PROXY)


//设置缓存方式、时长、地址


.addNetworkInterceptor(new CacheIntercepter())


.addInterceptor(new HeaderInterceptor())


.cache(cache)


.sslSocketFactory(TrustAllCerts.createSSLSocketFactory())


.hostnameVerifier(new TrustAllCerts.TrustAllHostnameVerifier());


if (BuildConfig.DEBUG) { // 判断是否为 debug


// 如果为 debug 模式,则添加日志拦截器


HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {


@Override


public void log(@NotNull String message) {


Log.i("hxg_http", message);


}


});


logging.setLevel(HttpLoggingInterceptor.Level.BASIC);


builder.addInterceptor(logging);


}


okHttpClient = builder.build();


}


private HttpEngine.TypeEnum mMediaType = HttpEngine.TypeEnum.FORM;


public void setMediaType(HttpEngine.TypeEnum mediaType) {


this.mMediaType = mediaType;


}


/**


  • get 请求

  • @param url

  • @param params

  • @return


*/


public void get(String url, Map<String, Object> params, HttpObserver observer) {


String execute = execute(url, params, observer);


if (execute != null) {


observer.onSuccess(execute);


} else {


observer.onError(new RuntimeException("网络连接出错"));


}


}


/**


  • post 请求

  • @param url

  • @param params

  • @return


*/


public void post(String url, Map<String, Object> params, HttpObserver observer) {


String execute = executePost(url, params);


if (execute != null) {


observer.onSuccess(execute);


} else {


observer.onError(new RuntimeException("网络连接出错"));


}


}


public void postText(String url, String stringJsonOrXml, HttpObserver observer) {


String execute = executePostText(url, stringJsonOrXml, observer);


if (execute != null) {


observer.onSuccess(execute);


} else {


observer.onError(new RuntimeException("网络连接出错"));


}


}


private String executePost(String url, Map<String, Object> params) {


try {


Response execute = postCall(sBaseUrl + url, params).execute();


ResponseBody body = execute.body();


return body.string();


} catch (IOException e) {


e.printStackTrace();


}


return null;


}


private String executePostText(String url, String stringJsonOrXml, HttpObserver observer) {


try {


Response execute = postCall(sBaseUrl + url, stringJsonOrXml).execute();


ResponseBody body = execute.body();


return body.string();


} catch (IOException e) {


e.printStackTrace();


observer.onError(e);


}


return null;


}


/**


  • Post 请求

  • @param url

  • @param params

  • @return


*/


private Call postCall(String url, Map<String, Object> params) {


RequestBody requestBody = appendBody(params, mMediaType);


Request.Builder builder = new Request.Builder();


Request request = builder.post(requestBody).url(url).build();


Call call = okHttpClient.newCall(request);


return call;


}


private Call postCall(String url, String stringJsonOrXml) {


MediaType mediaType = MediaType.parse(getTypeEnum(mMediaType));//"类型,字节码"


RequestBody requestBody = RequestBody.create(mediaType, stringJsonOrXml);


Request.Builder builder = new Request.Builder();


Request request = builder.post(requestBody).url(url).build();


Call call = okHttpClient.newCall(request);


return call;


}


/**


  • 组装 post 请求参数 body

  • @param params

  • @return


*/


private RequestBody appendBody(Map<String, Object> params, HttpEngine.TypeEnum mediaType) {


MultipartBody.Builder builder = new MultipartBody.Builder()


.setType(getMediaType(mediaType));


addParams(builder, params);


return builder.build();


}


/**


  • 添加参数

  • 判断是否能上传文件


*/


private void addParams(MultipartBody.Builder builder, Map<String, Object> params) {


if (params != null && !params.isEmpty()) {


for (String key : params.keySet()) {


Object value = params.get(key);


if (value instanceof File) {


File file = (File) value;


builder.addFormDataPart(key, file.getName(),


RequestBody.create(MediaType


.parse(guessMineType(file.getAbsolutePath())),


file));


} else if (value instanceof List) {


//代表提交的是 List 集合


try {


List<File> fileList = (List<File>) value;


for (int i = 0; i < fileList.size(); i++) {


//获取文件


File file = fileList.get(i);


builder.addFormDataPart(key + i, file.getName(),


RequestBody.create(MediaType


.parse(guessMineType(file.getAbsolutePath())),


file));


}


} catch (Exception e) {


e.printStackTrace();


}


} else {


builder.addFormDataPart(key, String.valueOf(value));


}


}


}


}


private String guessMineType(String path) {


FileNameMap fileNameMap = URLConnection.getFileNameMap();


String contentTypeFor = fileNameMap.getContentTypeFor(path);


if (contentTypeFor == null) {


contentTypeFor = "application/octet-stream";


}


return contentTypeFor;


}


private String getTypeEnum(HttpEngine.TypeEnum typeEnum) {


switch (typeEnum) {


case XML:


return "application/xml; charset=utf-8";


case JSON:


return "application/json; charset=utf-8";


case URLENCODED:


return "application/x-www-form-urlencoded;charset=utf-8";


}


return "application/json; charset=utf-8";


}


private MediaType getMediaType(HttpEngine.TypeEnum typeEnum) {


switch (typeEnum) {


case MIXED:


return MultipartBody.MIXED;


case ALTERNATIVE:


return MultipartBody.ALTERNATIVE;


case DIGEST:


return MultipartBody.DIGEST;


case PARALLEL:


return MultipartBody.PARALLEL;


case FORM:


return MultipartBody.FORM;


}


return MultipartBody.FORM;


}


/**


  • get 请求

  • @param url

  • @param params

  • @return


*/


private Call getCall(String url, Map<String, Object> params) {


String jointUrl = URLUtil.jointParams(sBaseUrl + url, params);


Request.Builder builder = new Request.Builder();


Request request = builder.get().url(jointUrl).build();


Call call = okHttpClient.newCall(request);


return call;


}


private String execute(String url, Map<String, Object> params, HttpObserver observer) {


try {


Response execute = getCall(url, params).execute();


ResponseBody body = execute.body();


return body.string();


} catch (IOException e) {


e.printStackTrace();


observer.onError(e);


}


return null;


}


}


  • HttpEngine


public class HttpEngine {


enum TypeEnum {


XML,


JSON,


URLENCODED,


MIXED,


ALTERNATIVE,


DIGEST,


PARALLEL,


FORM


}


}


  • URLUtil


public class URLUtil {


/**


  • 拼接参数


*/


public static String jointParams(String url,Map<String,Object> params){


if (params==null||params.size()<=0){


return url;


}


StringBuffer stringBuffer=new StringBuffer(url);


if (!url.contains("?")){


stringBuffer.append("?");


}else {


if (!url.endsWith("?")){


stringBuffer.append("&");


}


}


for (Map.Entry<String, Object> entry : params.entrySet()) {


stringBuffer.append(entry.getKey()+"="+entry.getValue()+"&");


}


stringBuffer.deleteCharAt(stringBuffer.length()-1);


return stringBuffer.toString();


}


/**


  • 解析一个类上面的 class 信息


*/


public static Class<?> analysisClazzInfo(Object object){


Type getType = object.getClass().getGenericSuperclass();


Type[] params = ((ParameterizedType) getType).getActualTypeArguments();


return (Class<?>) params[0];


}


}


  • 回调


public interface HttpObserver {


void onError(@NonNull Throwable e);


void onSuccess(String s);


}


import com.alibaba.fastjson.JSON;


import com.yumakeji.rxjava.network.bean.Result;


import com.yumakeji.rxjava.network.error.HttpThrowable;


import com.yumakeji.rxjava.network.error.ThrowableHandler;


import com.yumakeji.rxjava.network.unify.UnifyCallback;


import org.json.JSONException;


import org.json.JSONObject;


import java.lang.reflect.ParameterizedType;


import io.reactivex.rxjava3.annotations.NonNull;


public abstract class PagingHttpCallback<T> implements HttpObserver {


@Override


public void onSuccess(String result) {


try {


JSONObject jsonObject = new JSONObject(result);


Result result1 = new Result();


result1.setCode(jsonObject.getInt("code"));


result1.setMessage(jsonObject.getString("message"));


result1.data = jsonObject.getString("data");


if (!result1.isOk()) {


UnifyCallback.handleUnifyCode(result1.getCode(), result1.getMessage());


onFail(result1.getCode(), result1.getMessage());


return;


}


//解析,获取类上面的泛型


Class<T> dataClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())


.getActualTypeArguments()[0];


T data = JSON.parseObject(result1.data.toString(), dataClass);


onNext(data);


} catch (JSONException e) {


e.printStackTrace();


}


}


protected abstract void onNext(T data);


protected abstract void onFail(int code, String message);


@Override


public void onError(@NonNull Throwable throwable) {


if (throwable instanceof Exception) {


onFail(ThrowableHandler.handleThrowable(throwable));


} else {


onFail(new HttpThrowable(HttpThrowable.UNKNOWN, "未知错误", throwable));


}


}


//应用中具体实现的是下面这个 onFail 方法


private void onFail(HttpThrowable httpThrowable) {


onFail(httpThrowable.errorType, httpThrowable.message);


}


}



其他

DataSource



  • MutableItemKeyedDataSource


package com.paging.study.datasource;


import android.annotation.SuppressLint;


import androidx.annotation.NonNull;


import androidx.arch.core.executor.ArchTaskExecutor;


import androidx.paging.ItemKeyedDataSource;


import androidx.paging.PagedList;


import java.util.ArrayList;


import java.util.Collections;


import java.util.List;


/**


  • 一个可变更的 ItemKeyedDataSource 数据源

  • <p>

  • 工作原理是:我们知道 DataSource 是会被 PagedList 持有的。

  • 一旦,我们调用了 new PagedList.Builder<Key, Value>().build(); 那么就会立刻触发当前 DataSource 的 loadInitial()方法,而且是同步

  • 详情见 ContiguousPagedList 的构造函数,而我们在当前 DataSource 的 loadInitial()方法中返回了 最新的数据集合 data。

  • 一旦,我们再次调用 PagedListAdapter#submitList()方法 就会触发差分异计算 把新数据变更到列表之上了。

  • @param <Key>

  • @param <Value>


*/


@SuppressLint("RestrictedApi")


public abstract class MutableItemKeyedDataSource<Key, Value> extends ItemKeyedDataSource<Key, Value> {


private ItemKeyedDataSource mDataSource;


public List<Value> data = new ArrayList<>();


public PagedList<Value> buildNewPagedList(PagedList.Config config) {


PagedList<Value> pagedList = new PagedList.Builder<Key, Value>(this, config)


.setFetchExecutor(ArchTaskExecutor.getIOThreadExecutor())


.setNotifyExecutor(ArchTaskExecutor.getMainThreadExecutor())


.build();


return pagedList;


}


public MutableItemKeyedDataSource(ItemKeyedDataSource dataSource) {


mDataSource = dataSource;


}


@Override


public void loadInitial(@NonNull LoadInitialParams<Key> params, @NonNull LoadInitialCallback<Value> callback) {


callback.onResult(data);


}


@Override


public void loadAfter(@NonNull LoadParams<Key> params, @NonNull LoadCallback<Value> callback) {


if (mDataSource != null) {


//一旦 和当前 DataSource 关联的 PagedList 被提交到 PagedListAdapter。那么 ViewModel 中创建的 DataSource 就不会再被调用了


//我们需要在分页的时候 代理一下 原来的 DataSource,迫使其继续工作


mDataSource.loadAfter(params, callback);


}


}


@Override


public void loadBefore(@NonNull LoadParams<Key> params, @NonNull LoadCallback<Value> callback) {


callback.onResult(Collections.emptyList());


}


@NonNull


@Override


public abstract Key getKey(@NonNull Value item);


}


  • MutablePageKeyedDataSource


package com.paging.study.datasource;


import android.annotation.SuppressLint;


import androidx.annotation.NonNull;


import androidx.arch.core.executor.ArchTaskExecutor;


import androidx.paging.PageKeyedDataSource;


import androidx.paging.PagedList;


import java.util.ArrayList;


import java.util.Collections;


import java.util.List;


/**


  • 具体原理见 {@link MutableItemKeyedDataSource}

  • @param <Value>


*/


@SuppressLint("RestrictedApi")


public class MutablePageKeyedDataSource<Value> extends PageKeyedDataSource<Integer, Value> {


public List<Value> data = new ArrayList<>();


public PagedList<Value> buildNewPagedList(PagedList.Config config) {


PagedList<Value> pagedList = new PagedList.Builder<Integer, Value>(this, config)


.setFetchExecutor(ArchTaskExecutor.getIOThreadExecutor())


.setNotifyExecutor(ArchTaskExecutor.getMainThreadExecutor())


.build();


return pagedList;


}


@Override


public void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Integer, Value> callback) {


callback.onResult(data, null, null);


}


@Override


public void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Value> callback) {


callback.onResult(Collections.emptyList(), null);


}


@Override


public void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Integer, Value> callback) {


callback.onResult(Collections.emptyList(), null);


}


}


  • javabean


public class Teacher extends BaseResult {


private int current;


private int pages;


private int size;


private int total;


private List<RecordsBean> records;


@Override


public boolean equals(Object o) {


if (this == o) return true;


if (!(o instanceof Teacher)) return false;


Teacher teacher = (Teacher) o;


return getCurrent() == teacher.getCurrent() &&


getPages() == teacher.getPages() &&


getSize() == teacher.getSize() &&


getTotal() == teacher.getTotal() &&


Objects.equals(getRecords(), teacher.getRecords());


}


@Override


public int hashCode() {


return Objects.hash(getCurrent(), getPages(), getSize(), getTotal(), getRecords());


}


public int getCurrent() {


return current;


}


public void setCurrent(int current) {


this.current = current;


}


public int getPages() {


return pages;


}


public void setPages(int pages) {


this.pages = pages;


}


public int getSize() {


return size;


}


public void setSize(int size) {


this.size = size;


}


public int getTotal() {


return total;


}


public void setTotal(int total) {


this.total = total;


}


public List<RecordsBean> getRecords() {


return records;


}


public void setRecords(List<RecordsBean> records) {


this.records = records;


}


public static class RecordsBean {


private String createTime;


private int difficultyIndex;


private String direction;


private String headImgUrl;


private int isVip;


private String label;


private String paintingId;


private String paintingName;


private String readCount;


private String showNew;


private String studyAge;


private String titlePage;


private int type;


private String userName;


private String videoId;


private String videoName;


private List<LabelListBean> labelList;


@Override


public boolean equals(Object o) {


if (this == o) return true;


if (!(o instanceof RecordsBean)) return false;


RecordsBean that = (RecordsBean) o;


return getDifficultyIndex() == that.getDifficultyIndex() &&


getIsVip() == that.getIsVip() &&


getType() == that.getType() &&


Objects.equals(getCreateTime(), that.getCreateTime()) &&


Objects.equals(getDirection(), that.getDirection()) &&


Objects.equals(getHeadImgUrl(), that.getHeadImgUrl()) &&


Objects.equals(getLabel(), that.getLabel()) &&


Objects.equals(getPaintingId(), that.getPaintingId()) &&


Objects.equals(getPaintingName(), that.getPaintingName()) &&


Objects.equals(getReadCount(), that.getReadCount()) &&


Objects.equals(getShowNew(), that.getShowNew()) &&


Objects.equals(getStudyAge(), that.getStudyAge()) &&


Objects.equals(getTitlePage(), that.getTitlePage()) &&


Objects.equals(getUserName(), that.getUserName()) &&


Objects.equals(getVideoId(), that.getVideoId()) &&


Objects.equals(getVideoName(), that.getVideoName()) &&


Objects.equals(getLabelList(), that.getLabelList());


}


@Override


public int hashCode() {


return Objects.hash(getCreateTime(), getDifficultyIndex(), getDirection(), getHeadImgUrl(), getIsVip(), getLabel(), getPaintingId(), getPaintingName(), getReadCount(), getShowNew(), getStudyAge(), getTitlePage(), getType(), getUserName(), getVideoId(), getVideoName(), getLabelList());


}


public String getCreateTime() {


return createTime;


}


public void setCreateTime(String createTime) {


this.createTime = createTime;


}


public int getDifficultyIndex() {


return difficultyIndex;


}


public void setDifficultyIndex(int difficultyIndex) {


this.difficultyIndex = difficultyIndex;


}


public String getDirection() {


return direction;


}


public void setDirection(String direction) {


this.direction = direction;


}


public String getHeadImgUrl() {


return headImgUrl;


}


public void setHeadImgUrl(String headImgUrl) {


this.headImgUrl = headImgUrl;


}


public int getIsVip() {


return isVip;


}


public void setIsVip(int isVip) {


this.isVip = isVip;


}


public String getLabel() {


return label;


}


public void setLabel(String label) {


this.label = label;


}


public String getPaintingId() {


return paintingId;


}


public void setPaintingId(String paintingId) {


this.paintingId = paintingId;


}


public String getPaintingName() {


return paintingName;


}


public void setPaintingName(String paintingName) {


this.paintingName = paintingName;


}

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
第五章:paging使用