哥搜索了几天,都没有找到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);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 下面是一个简单的Java代码示例,实现了将List进行分页的功能。 ```Java import java.util.List; import java.util.ArrayList; public class Pagination { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); for (int i = 1; i <= 100; i++) { list.add(i); } int pageSize = 10; int totalPage = (list.size() + pageSize - 1) / pageSize; for (int i = 1; i <= totalPage; i++) { int startIndex = (i - 1) * pageSize; int endIndex = startIndex + pageSize - 1; if (endIndex > list.size() - 1) { endIndex = list.size() - 1; } List<Integer> subList = list.subList(startIndex, endIndex + 1); System.out.println("第" + i + "页数据:" + subList); } } } ``` 这段代码首先定义了一个长度为 100 的 List,然后定义了每页的大小为 10。接下来使用了循环遍历这个 List,每次计算出每页的起始索引和结束索引,并使用List的subList()方法获取该页的数据。最后输出每页的数据。 ### 回答2: 当使用Java编写一个分页功能时,我们可以使用以下步骤: 1. 首先,我们需要定义一个用于存储每页数据的数据结构,例如一个列表或数组。 2. 接下来,我们需要定义每页显示的数据数量,例如每页显示10个数据。 3. 然后,我们需要获取总数据量,例如从数据库中查询总共有100条数据。 4. 在实现分页之前,我们需要计算总页数。计算方法是将总数据量除以每页显示的数据数量并向上取整。在这个例子中,总页数为 100/10 = 10页。 5. 现在,我们需要定义一个方法来获取指定页数的数据。这个方法需要接收页码作为参数,并返回对应页码的数据。 6. 在获取数据的方法中,我们需要根据指定页码计算起始索引和结束索引。起始索引可以通过公式 (页码-1) * 每页数据量 计算得到,而结束索引则是起始索引加上每页数据量。在我们的例子中,如果想获取第3页的数据,起始索引为 (3-1) * 10 = 20,结束索引为 20 + 10 = 30。 7. 最后,我们可以调用获取数据的方法并传递所需页码作为参数,然后将返回的数据展示给用户。 总的来说,使用Java编写一个分页功能需要定义数据结构、计算总页数、获取指定页码的数据等步骤。这样就能够实现一个简单的分页功能。 ### 回答3: 分页是将大量的数据按照每页显示固定数量的方式进行展示,可以提高用户浏览数据的效率。下面是用 Java 实现分页的一个示例: ```java public class Paging { private int totalItems; private int itemsPerPage; public Paging(int totalItems, int itemsPerPage) { this.totalItems = totalItems; this.itemsPerPage = itemsPerPage; } public int getPages() { return (int) Math.ceil((double) totalItems / itemsPerPage); } public List<Integer> getPageData(int page) { List<Integer> pageData = new ArrayList<>(); int startIndex = (page - 1) * itemsPerPage; int endIndex = Math.min(startIndex + itemsPerPage, totalItems); for (int i = startIndex; i < endIndex; i++) { pageData.add(i + 1); } return pageData; } public static void main(String[] args) { int totalItems = 100; int itemsPerPage = 10; Paging paging = new Paging(totalItems, itemsPerPage); int totalPages = paging.getPages(); System.out.println("总页数:" + totalPages); int currentPage = 2; List<Integer> pageData = paging.getPageData(currentPage); System.out.println("当前页数据:"); for (int item : pageData) { System.out.print(item + " "); } } } ``` 以上代码定义了一个 `Paging` 类,通过传入总数据量和每页显示的数量来初始化分页对象。其中,`getPages` 方法用于计算总页数,`getPageData` 方法根据传入的页码获取当前页的数据。 在 `main` 方法中,我们定义了总数据量为 100,每页显示 10 条数据,然后通过 `Paging` 类计算总页数并显示,最后获取第 2 页的数据并进行展示。 注意,此处示例仅为简化示例,实际应用中还需要考虑异常处理、数据库查询等其他因素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值