哥搜索了几天,都没有找到paging3 的java完整版本实现,

现在主流都是kotlin 了吧,毕竟 kotlin 是谷歌的亲儿子。谷歌在这方面都是非常鸡贼的,
当年 HttpClient 和httpconnection 之争,硬是最后 httpconnection 胜出,但最终败于okhttp,不过鸡贼的谷歌,迟早弄掉okhttp的, RXJAVA 不就被谷歌用livedata 弄掉了嘛。再来从新走一轮 paging3的流程:
以WanAndroid的接口为例,接口地址为:https://www.wanandroid.com/article/list/1/json,数据源的代码如下。
先定义API:

public interface WanAndroidApi {
    @GET("article/list/{page}/json")
    Call<ArticleBean> getArticleBean(@Path("page") int page);
}

再定义 RetrofitClient ,这个简单,不复述了。
定义一个Paging3DataSource:

public class Paging3DataSource extends PagingSource<Integer, DatasBean> {
    @Nullable
    @Override
    public Object load(@NonNull LoadParams<Integer> loadParams, @NonNull Continuation<? super LoadResult<Integer, DatasBean>> continuation) {
        int page = 0;
        if (loadParams.getKey() != null) {
            page = loadParams.getKey();
        }
        //获取网络数据
        ArticleBean result = getbean(page);
        //须要加载的数据
        List<DatasBean> datas = result.getData().getDatas();
        //如果能够往上加载更多就设置该参数,否则不设置
        String prevKey = null;
        //加载下一页的key 如果传null就阐明到底了
        int nextKey = 0;
        if (result.getData().getCurPage() == result.getData().getPageCount()) {
            nextKey = 0;
        } else {
            nextKey = page + 1;
        }
        return new LoadResult.Page<>(datas, prevKey, nextKey);
    }
    
    public ArticleBean getbean(int page) {
    //这里主要是使用了future.get() 阻塞了线程,直到有结果才返回,避免为空。
        Call<ArticleBean> observable = RetrofitClient.getInstance().createApi(WanAndroidApi.class).getA(page);
        ArticleBean bean = ExecutorUtil.submit(new Callable<ArticleBean>() {
            @Override
            public ArticleBean call() throws Exception {
                return observable.execute().body();
            }
        });
        return bean;
    }
}

ExecutorUtil工具类:

public class ExecutorUtil {
    private static ExecutorService executor = Executors.newCachedThreadPool();

    public static void execute(Runnable runnable) {
        executor.execute(runnable);
    }

    public static <T> T submit(Callable<T> callable) {
        Future<T> future = executor.submit(callable);
        try {
            return future.get();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

后面是标准流程了。
定义Paging3ViewModel :

public class Paging3ViewModel extends ViewModel {

    PagingConfig pagingConfig = new PagingConfig(20, 3);

    public LiveData<PagingData<DatasBean>> getArticleData() {
        CoroutineScope viewModelScope = ViewModelKt.getViewModelScope(this);
        Pager<Integer, DatasBean> pager = new Pager<>(pagingConfig, () -> new Paging3DataSource());
      LiveData<PagingData<DatasBean>> cachedResult = PagingLiveData.cachedIn(PagingLiveData.getLiveData(pager), viewModelScope);
        return cachedResult;
    }

}

定义Paging3Adapter:

public class Paging3Adapter extends PagingDataAdapter<DatasBean, Paging3Adapter.ViewHolder> {


    public Paging3Adapter() {
        super(itemCallback);
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycleview, parent, false);
        return new Paging3Adapter.ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
       DatasBean bean = getItem(position);
        if (bean != null) {
            holder.desc.setText(bean.getDesc());
            holder.time.setText(String.valueOf(bean.getPublishTime()));
            holder.type.setText(bean.getType()+"-");
            holder.auth.setText(bean.getAuthor());
        }
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Loge.e(bean.toString());
            }
        });
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView desc;
        TextView time;
        TextView type;
        TextView auth;

        public ViewHolder(View itemView) {
            super(itemView);
            desc = itemView.findViewById(R.id.desc);
            time = itemView.findViewById(R.id.time);
            type = itemView.findViewById(R.id.type);
            auth = itemView.findViewById(R.id.auth);
        }
    }


    public static DiffUtil.ItemCallback<DatasBean> itemCallback = new DiffUtil.ItemCallback<DatasBean>() {
        @Override
        public boolean areItemsTheSame(@NonNull DatasBean oldItem, @NonNull DatasBean newItem) {
            return oldItem.getId() == newItem.getId();
        }

        @SuppressLint("DiffUtilEquals")
        @Override
        public boolean areContentsTheSame(@NonNull DatasBean oldItem, @NonNull DatasBean newItem) {
            return oldItem.equals(newItem);
        }
    };
}

最后是fragment 使用:

public class Paging3_Fragment extends BaseFragment<Paging3FragmentBinding> {
    private final String TAG = "MainActivity";
    private Paging3Adapter adapter;

    @Override
    protected int getLayoutId() {
        return R.layout.paging3_fragment;
    }

    @Override
    protected void initView() {
        initRecyclerView();
    }

    private void initRecyclerView() {
        adapter = new Paging3Adapter();
        binding.recyclerViewPaging3Test6.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
        binding.recyclerViewPaging3Test6.setLayoutManager(new LinearLayoutManager(getContext()));
        binding.recyclerViewPaging3Test6.setAdapter(adapter);

        Paging3ViewModel viewModel = new ViewModelProvider(this).get(Paging3ViewModel.class);

        viewModel.getArticleData().observe(this, pagingData -> adapter.submitData(getLifecycle(), pagingData));
    }

    @Override
    protected void initData() {
    }
}

其实上文参考了,https://lequ7.com/guan-yu-javaandroidjetpack-jia-gou-zu-jian-jiu-zhi-paging.html 作者,但是他没有给出 Paging3DataSource 获取数据的实现,主要是子线程获取数据,到主线程那里。我还找到了一个其他的实现方法。改写一个

/**
 * 实现可以直接返回数据类的核心类
 */
public class DirectCallAdapterFactory extends CallAdapter.Factory {
    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        final Type responseType = getResponseType(returnType);

        return new CallAdapter<Object, Object>() {
            public Type responseType() {
                return responseType;
            }

            public Object adapt(Call<Object> call) {
                // todo 可以在这里判断接口数据格式
                //                    Loge.e(Thread.currentThread().getName());
//                    return call.execute().body();
                return ExecutorUtil.submit(new Callable<Object>() {
                    @Override
                    public Object call() throws Exception {
                        return call.execute().body();
                    }
                });
            }
        };
    }

    private Type getResponseType(Type type) {
        if (type instanceof WildcardType) {
            return ((WildcardType) type).getUpperBounds()[0];
        }
        return type;
    }
}

在RetrofitClient上增加一个转换即可:
public RetrofitClient() {
mRetrofit=new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(new DirectCallAdapterFactory()) //重点是这里,
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.client(getClient())
.build();
}
另外 API,也改一下,直接返回 实体bean 即可:
public interface WanAndroidApi {
@GET(“article/list/{page}/json”)
Call getA(@Path(“page”) int page);

@GET("article/list/{page}/json")
ArticleBean getArticleBean(@Path("page") int page);

}
这样取数据的时候,就可以直接的使用了

 @Override
    protected void initData() {
        ArticleBean articleBean=RetrofitClient.getInstance().createApi(WanAndroidApi.class).getArticleBean(0);
        Loge.e(articleBean.toString());
    }

直接返回实体bean也很方便.

上面的 Paging3DataSource是不完善的,下面补充一个完善的Paging3DataSource实现:

public class Paging3DataSource_03 extends ListenableFuturePagingSource<Integer, DatasBean> {
    private ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());

    @NonNull
    @Override
    public ListenableFuture<LoadResult<Integer, DatasBean>> loadFuture(@NonNull LoadParams<Integer> loadParams) {
        Integer nextPageNumber = loadParams.getKey();
        if (nextPageNumber == null) {
            nextPageNumber = 0;//从第0页开始加载
        }
        Integer finalNextPageNumber = nextPageNumber;

        ListenableFuture<LoadResult<Integer, DatasBean>> listenableFuture = Futures.transform(executorService.submit(new Callable<List<DatasBean>>() {
            @Override
            public List<DatasBean> call() throws Exception {
                Loge.e(Thread.currentThread().getName() + ":当前线程");
                Call<ArticleBean> call = RetrofitClient.getInstance().createApi(WanAndroidApi.class).getA(finalNextPageNumber);
                ArticleBean articleBean = call.execute().body();


                return articleBean.getData().getDatas();
            }
        }), new Function<List<DatasBean>, LoadResult<Integer, DatasBean>>() {
            @Nullable
            @Override
            public LoadResult<Integer, DatasBean> apply(@Nullable List<DatasBean> input) {
                return new LoadResult.Page<>(input, finalNextPageNumber == 0 ? null : finalNextPageNumber - 1, input.isEmpty() ? null : finalNextPageNumber + 1);
            }
        }, executorService);


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

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值