使用 Retrofit 滚动到 RecyclerView 底部时添加更多项目

讨价还价23

我一直在关注教程来实现分页,并且我非常关注它,但我不确定我应该如何修改我当前的活动来实现OnLoadMoreListener. 我正在使用改造中的 ApiService 来加载数据,这与生成随机字符串的教程不同。

这是我当前的 RecyclerView 适配器的样子:

public class CuratedSectionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static int VIEW_TYPE_HEADER = 0;
    private static int VIEW_TYPE_ITEM = 1;
    private static int VIEW_TYPE_LOADING = 2;

    private int lastVisibleItem, totalItemCount;
    private int visibleThreshold = 2;
    private boolean isLoading;

    private List<Object> itemList;
    private OnLoadMoreListener onLoadMoreListener;

    public CuratedSectionAdapter(RecyclerView recyclerView, List<Object> itemList) {
        this.itemList = itemList;

        final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                    if (onLoadMoreListener != null) {
                        onLoadMoreListener.onLoadMore();
                    }
                    isLoading = true;
                }
            }
        });
    }

    private class ItemViewHolder extends RecyclerView.ViewHolder {

        RecyclerView itemRecyclerView;
        CuratedSectionNestedAdapter nestedAdapter;
        LinearLayoutManager layoutManager;

        ItemViewHolder(View view) {
            super(view);
            itemRecyclerView = view.findViewById(R.id.recyclerView_nested);
            layoutManager = new LinearLayoutManager(view.getContext(), LinearLayoutManager.HORIZONTAL, false);
        }
    }

    private class HeaderViewHolder extends RecyclerView.ViewHolder {
        TextView textViewHeader;
        Typeface montserratMedium = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/Montserrat-Medium.ttf");

        HeaderViewHolder(View view) {
            super(view);
            textViewHeader = view.findViewById(R.id.textView_header);
            textViewHeader.setTypeface(montserratMedium);
        }
    }

    private class LoadingViewHolder extends RecyclerView.ViewHolder {
        public ProgressBar progressBar;

        public LoadingViewHolder(View view) {
            super(view);
            progressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (holder.getItemViewType() == VIEW_TYPE_HEADER) {
            HeaderViewHolder viewHolder = (HeaderViewHolder) holder;
            CuratedSectionHeader header = (CuratedSectionHeader) itemList.get(position);

            viewHolder.textViewHeader.setText(header.getHeaderName());
        } else if (holder.getItemViewType() == VIEW_TYPE_ITEM) {
            ItemViewHolder viewHolder = (ItemViewHolder) holder;
            List<CuratedSectionItem> items = (List<CuratedSectionItem>) itemList.get(position);

            if (viewHolder.nestedAdapter != null) {
                viewHolder.nestedAdapter.setItems(items);
            } else {
                viewHolder.nestedAdapter = new CuratedSectionNestedAdapter(items);
                viewHolder.itemRecyclerView.setLayoutManager(viewHolder.layoutManager);
                viewHolder.itemRecyclerView.setAdapter(viewHolder.nestedAdapter);
            }
        } else if (holder.getItemViewType() == VIEW_TYPE_LOADING) {
            LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
            loadingViewHolder.progressBar.setIndeterminate(true);
        }

    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_HEADER) {
            return new HeaderViewHolder(LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.main_explore_header_row, parent, false));
        } else if (viewType == VIEW_TYPE_ITEM) {
            return new ItemViewHolder(LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.main_explore_row, parent, false));
        } else if (viewType == VIEW_TYPE_LOADING) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_loading, parent, false);
            return new LoadingViewHolder(view);
        }

        throw new RuntimeException("Adapter " + viewType + "not found");
    }

    @Override
    public int getItemCount() {
        return itemList.size();
    }

    @Override
    public int getItemViewType(int position) {

        if (itemList.get(position) instanceof  CuratedSectionHeader) {
            return VIEW_TYPE_HEADER;
        } else {
            return itemList.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
        }
    }

    public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
        this.onLoadMoreListener = mOnLoadMoreListener;
    }

    public void setLoaded() {
        isLoading = false;
    }
}

我的活动的当前架构使用私有类进行 API 调用和加载数据。目前,所有项目都会一次加载,但理想情况下一次应该只加载 2 个项目。当我滚动到底部时,我不确定应该如何通过再次调用 API 服务来加载其他项目。至少,我确信我将不得不以curatedSectionAdapter.setOnLoadMoreListener某种方式使用

这是我目前加载所有项目的方式:

private class Sections {
    List<CuratedSection> sections = new ArrayList<>();
    public Thread[] thread;

    private Sections() {}

    public void setSections(ArrayList<CuratedSection> sections) {
        this.sections = sections;
    }

    public void setSectionStories(String sectionId, List<CuratedSectionItem> stories) {
        for(CuratedSection s : sections){
            if(s.id != null && s.id.equals(sectionId)) {
                s.stories = stories;
            }
        }
    }

    public void loadStories(String sessionKey) {
        thread = new Thread[sections.size()];
        for( int s = 0; s < sections.size(); s++) {
            thread[s] = new Thread(new LoadStories(sessionKey, sections.get(s)));
            thread[s].start();
        }
        for( int f = 0; f < sections.size(); f++) {
            try {
                thread[f].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        recyclerView.setLayoutManager(layoutManager);
        curatedSectionAdapter = new CuratedSectionAdapter(recyclerView, this.getAdapterInfo());
        recyclerView.setAdapter(curatedSectionAdapter);
    }

    public void loadSections(int numSections) {
        swipeRefreshLayout.setRefreshing(false);
        LoadSections load = new LoadSections(numSections);
        load.run();
    }

    public List<Object> getAdapterInfo() {
        List<Object> list = new ArrayList<>();

        for (int i = 0; i < sections.size(); i++) {
            CuratedSection section = sections.get(i);
            CuratedSectionHeader header = new CuratedSectionHeader();
            header.setHeaderName(section.header);

            list.add(header);
            list.add(section.stories);
        }

        return list;
    }
}


private class LoadSections implements Runnable {

    int numSections;

    LoadSections(int numSections) {
        this.numSections = numSections;
    }

    @Override
    public void run() {
        SharedPreferences prefs = getSharedPreferences("user_session", MODE_PRIVATE);
        final String sessionKey = prefs.getString("session_key", null);

        Call<JsonArray> call;
        call = TravelersApi.endpoint().getCuratedSections(sessionKey);

        call.enqueue(new Callback<JsonArray>() {
            @Override
            public void onResponse(Call<JsonArray> call, Response<JsonArray> response) {
                if(response.code() != 200) {
                    Toast.makeText(getApplicationContext(), "Cannot load page as of the moment.", Toast.LENGTH_SHORT).show();
                    return;
                }
                JsonArray rawSections = response.body();
                if(rawSections.size() == 0) {
                    //TODO: show placeholder
                    return;
                }
                ArrayList<CuratedSection> sections = new ArrayList<>();
                for(int i = 0; i < numSections; i++) {
                    JsonObject jSection = rawSections.get(i).getAsJsonObject();
                    final CuratedSection section = new CuratedSection();
                    section.id = jSection.get("id").getAsString();
                    section.header = jSection.get("section_header").getAsString();
                    section.topicCount = jSection.get("topic_count").getAsInt();
                    section.isShown = jSection.get("is_shown").getAsBoolean();
                    section.stories = new ArrayList<>();

                    sections.add(section);
                }
                curated.setSections(sections);
                curated.loadStories(sessionKey);

                spinner.clearAnimation();
                spinner.setVisibility(View.GONE);
                header.setVisibility(View.VISIBLE);
                swipeRefreshLayout.setVisibility(View.VISIBLE);

            }

            @Override
            public void onFailure(Call<JsonArray> call, Throwable t) {
                Log.d("ERROR!", t.toString());
                t.printStackTrace();
            }
        });
    }
}
ADM

您可以通过将滚动侦听器直接设置为回收器视图来实现此目的。

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            totalItemCount = linearLayoutManager.getItemCount();
            lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
            if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                // Call Load more method here to load next page data
               // Prevent multiple calls by using a boolean
                isLoading=true; // boolean to Prevent multiple calls
            }
        }
    });

OnLoadMoreListener是一个需要先注册的接口。对于分页,您的服务器应该处理分页计数。所以你还需要 api 在 page limit 上执行。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

滚动到RecyclerView的最底部

来自分类Dev

我希望 RecyclerView 在滚动到结尾时加载更多项目。我怎样才能得到这个?

来自分类Dev

如何使RecyclerView始终滚动到底部

来自分类Dev

RecyclerView是时自动滚动到和闪烁

来自分类Dev

在 recyclerview 中滚动滚动到视图底部而不是顶部

来自分类Dev

当recyclerview滚动/滚动到顶部时,展开appbarlayout

来自分类Dev

RecyclerView滚动到页面底部不会触发.addOnScrollListener的canScrollVertically

来自分类Dev

如何使用ExtJs滚动到网格底部

来自分类Dev

如何使用ExtJs滚动到网格底部

来自分类Dev

使用JS定位并滚动到表格底部

来自分类Dev

使用 Javascript 滚动到列表底部

来自分类Dev

在 RecyclerView 中检测当前滚动到哪个项目

来自分类Dev

使用Javascript滚动到底部时如何追加更多行

来自分类Dev

使用 GET 变量从数据库滚动到底部时加载更多 - PHP/Mysqli

来自分类Dev

使用JS / Jquery滚动到特定项目

来自分类Dev

当滚动到底部时,ListView自动添加更多内容

来自分类Dev

Android Studio Recyclerview 使用 Retrofit

来自分类Dev

使用 CustomListViewAdapter 时以编程方式滚动到 ListView 中的项目

来自分类Dev

滚动到视图之外时,将项目的状态保存在recyclerview中

来自分类Dev

将div onload滚动到底部,以及在使用新数据更新时滚动-angularjs

来自分类Dev

将div onload滚动到底部,以及在使用新数据更新时滚动-angularjs

来自分类Dev

ScrollViewer不能使用Avalonedit滚动到底部

来自分类Dev

ScrollViewer不能使用Avalonedit滚动到底部

来自分类Dev

如何使用jQuery向下滚动到底部子div

来自分类Dev

使用香草Javascript / CSS自动滚动到底部-Polymer

来自分类Dev

如何使用 Nightwatch.js 滚动到页面底部

来自分类Dev

滚动到ckeditor的底部

来自分类Dev

滚动到Meteorjs的底部

来自分类Dev

如何在 angular 上使用鼠标滚轮滚动到项目

Related 相关文章

  1. 1

    滚动到RecyclerView的最底部

  2. 2

    我希望 RecyclerView 在滚动到结尾时加载更多项目。我怎样才能得到这个?

  3. 3

    如何使RecyclerView始终滚动到底部

  4. 4

    RecyclerView是时自动滚动到和闪烁

  5. 5

    在 recyclerview 中滚动滚动到视图底部而不是顶部

  6. 6

    当recyclerview滚动/滚动到顶部时,展开appbarlayout

  7. 7

    RecyclerView滚动到页面底部不会触发.addOnScrollListener的canScrollVertically

  8. 8

    如何使用ExtJs滚动到网格底部

  9. 9

    如何使用ExtJs滚动到网格底部

  10. 10

    使用JS定位并滚动到表格底部

  11. 11

    使用 Javascript 滚动到列表底部

  12. 12

    在 RecyclerView 中检测当前滚动到哪个项目

  13. 13

    使用Javascript滚动到底部时如何追加更多行

  14. 14

    使用 GET 变量从数据库滚动到底部时加载更多 - PHP/Mysqli

  15. 15

    使用JS / Jquery滚动到特定项目

  16. 16

    当滚动到底部时,ListView自动添加更多内容

  17. 17

    Android Studio Recyclerview 使用 Retrofit

  18. 18

    使用 CustomListViewAdapter 时以编程方式滚动到 ListView 中的项目

  19. 19

    滚动到视图之外时,将项目的状态保存在recyclerview中

  20. 20

    将div onload滚动到底部,以及在使用新数据更新时滚动-angularjs

  21. 21

    将div onload滚动到底部,以及在使用新数据更新时滚动-angularjs

  22. 22

    ScrollViewer不能使用Avalonedit滚动到底部

  23. 23

    ScrollViewer不能使用Avalonedit滚动到底部

  24. 24

    如何使用jQuery向下滚动到底部子div

  25. 25

    使用香草Javascript / CSS自动滚动到底部-Polymer

  26. 26

    如何使用 Nightwatch.js 滚动到页面底部

  27. 27

    滚动到ckeditor的底部

  28. 28

    滚动到Meteorjs的底部

  29. 29

    如何在 angular 上使用鼠标滚轮滚动到项目

热门标签

归档