简体   繁体   English

使用翻新时滚动到RecyclerView的底部时添加更多项

[英]Adding more items when scrolling to the bottom of a RecyclerView while using Retrofit

I was following this tutorial to implement pagination, and I was following it keenly, but I am uncertain how I should modify my current activity to implement OnLoadMoreListener . 我一直在遵循教程来实现分页,并且一直在关注它,但是我不确定如何修改当前活动以实现OnLoadMoreListener I am using an ApiService from retrofit to load data, unlike the tutorial that generates random strings. 我正在使用ApiService进行改造以加载数据,这与生成随机字符串的教程不同。

This is how my current RecyclerView adapter looks like: 这是我当前的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;
    }
}

The current architecture of my activity uses private classes to make API calls and load the data. 我当前活动的体系结构使用私有类来进行API调用并加载数据。 At the moment, all items are loaded at once, but ideally there should be only 2 items loaded at a time. 目前,所有项目都可以一次加载,但理想情况下一次只能加载2个项目。 I am uncertain how I should load additional items by calling the API service again when I scroll to the bottom. 我不确定滚动到底部时如何再次调用API服务来加载其他项目。 At the very least, I am certain that I will have to use curatedSectionAdapter.setOnLoadMoreListener somehow. 至少,我确定我将不得不以某种方式使用curatedSectionAdapter.setOnLoadMoreListener

This is how I load all of the items at the moment: 这是我现在加载所有项目的方式:

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();
            }
        });
    }
}

You can achieve this by directly setting scroll listener to your recycler view. 您可以通过将滚动侦听器直接设置到回收站视图来实现。

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 is a interface you need to register it first. OnLoadMoreListener是您需要首先注册的接口。 For pagination your server should process the pagination count. 对于分页,服务器应处理分页计数。 So you also need the api to perform on page limit . 因此,您还需要该API来执行页面限制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Retrofit在recyclerView中正确加载更多项目? (科特琳) - How to properly load more items in a recyclerView, using Retrofit ? (kotlin) 滚动时检测 RecyclerView 何时到达最底部 position - Detect when RecyclerView reaches the bottom most position while scrolling 滚动查看时单击的项目 - RecyclerView items clicking while scrolling 当我使用RecyclerView和Retrofit时如何加载更多内容? - How to load more when i using RecyclerView and Retrofit? 滚动时RecyclerView获取IndexOutOfBoundsException(Retrofit2 +库部分RecyclerView) - RecyclerView gets IndexOutOfBoundsException when Scrolling (Retrofit2 + Library Section RecyclerView) 使用ProgressBar在底部向Endless Scroll RecyclerView添加项目 - Adding items to Endless Scroll RecyclerView with ProgressBar at bottom RecyclerView index=-1 快速滚动到底部时 - RecyclerView index=-1 when scrolling fast to the bottom "Android RecyclerView 项目在滚动时展开焦点" - Android RecyclerView items expand on focus while scrolling 滚动时 RecyclerView 中的项目显示不正确 - Incorrect displaying items in RecyclerView while scrolling 防止 RecyclerView 在滚动时更新项目 - Prevent RecyclerView from updating items while scrolling
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM