繁体   English   中英

实现无尽的recyclerview -android吗?

[英]Implement endless recyclerview -android?

所以我正在尝试实现无休止的recyclerview。 我在堆栈上阅读了其他教程和示例,但它们都不是直接的。 我正在寻找一个通用的答案,该答案可以应用于很多人的需求,包括我自己的需求。

目前,我有一个recyclerview +适配器工作,可以从后端获取数据并加载它。 现在,当我到达终点时,我想调用我的api方法以再次获取数据并将其加载到我的Recycler视图中。

这是我的Recycler视图初始化。

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        // Inflate the layout for this fragment
        rootView = inflater.inflate(R.layout.activity_9b_newsfeed , container, false);
        bindActivity();
        return rootView;
    }
    private void bindActivity()
    {
        progressBar = (ProgressBar) rootView.findViewById(R.id.newsfeed_PB);
        recyclerView = (RecyclerView) rootView.findViewById(R.id.newsfeed_RV);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity().getBaseContext());
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.setNestedScrollingEnabled(false);
        endlessScrollListener = new EndlessScrollListener()//no clue how the hell to use it.
        {
            @Override
            public boolean onLoadMore(int page, int totalItemsCount)
            {
                //when i reach my last post, this doesn't even get called..so don't really know how to use this.
                return false;
            }
        };
        recyclerView.addOnScrollListener(endlessScrollListener);

        GetPostsAsyncTask getPostsAsyncTask = new GetPostsAsyncTask();
        getPostsAsyncTask.execute();
    }

这是我的GetPostAsyncTask类,它获取我的帖子数据,将其封装到Post Objects中,然后推送到我的recyclerview中,该视图将帖子显示为类似新闻提要的功能。

 private class GetPostsAsyncTask extends AsyncTask<Void,Void,Void>
    {
        @Override
        protected Void doInBackground(Void... params)
        {
            if(doesPostListExist)
            {
                getNewsFeed = new GetNewsFeed(getActivity(),true,Global_Class.getInstance().getValue().user.getUsername());
                getNewsFeed.getMyNewsFeed();
            }
            else
            {
                getNewsFeed = new GetNewsFeed(getActivity(),false,Global_Class.getInstance().getValue().user.getUsername());
                getNewsFeed.getMyNewsFeed();
            }

            return null;
        }
        @Override
        public void onPostExecute(Void var)
        {
            progressBar.setVisibility(View.GONE);

            Calendar c = Calendar.getInstance();
            farTime = c.getTimeInMillis();
            Log.d(MY_NEWSFEED,"my far time is " + String.valueOf(farTime));

            if(getNewsFeed.isGetNewsFeedSuccess())
            {
                complexRecyclerViewAdapter = new ComplexRecyclerViewAdapter(getNewsFeed.getNewsFeedPost());//change getNewsFeed.getNewsFeedPost() -> postArrayList
                recyclerView.setAdapter(complexRecyclerViewAdapter);
                recyclerView.setItemAnimator(new DefaultItemAnimator());
                recyclerView.setNestedScrollingEnabled(false);

            }
        }
    }

这是endlessScrollListener类,我将其废弃在某个地方,我不知道如何使用它,但是在这里。

public abstract class EndlessScrollListener extends RecyclerView.OnScrollListener implements AbsListView.OnScrollListener {
    // The minimum number of items to have below your current scroll position
    // before loading more.
    private int visibleThreshold = 5;
    // The current offset index of data you have loaded
    private int currentPage = 0;
    // The total number of items in the dataset after the last load
    private int previousTotalItemCount = 0;
    // True if we are still waiting for the last set of data to load.
    private boolean loading = true;
    // Sets the starting page index
    private int startingPageIndex = 0;

    public EndlessScrollListener() {
    }

    public EndlessScrollListener(int visibleThreshold) {
        this.visibleThreshold = visibleThreshold;
    }

    public EndlessScrollListener(int visibleThreshold, int startPage) {
        this.visibleThreshold = visibleThreshold;
        this.startingPageIndex = startPage;
        this.currentPage = startPage;
    }


    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
    {
        // If the total item count is zero and the previous isn't, assume the
        // list is invalidated and should be reset back to initial state
        if (totalItemCount < previousTotalItemCount) {
            this.currentPage = this.startingPageIndex;
            this.previousTotalItemCount = totalItemCount;
            if (totalItemCount == 0) { this.loading = true; }
        }
        // If it's still loading, we check to see if the dataset count has
        // changed, if so we conclude it has finished loading and update the current page
        // number and total item count.
        if (loading && (totalItemCount > previousTotalItemCount)) {
            loading = false;
            previousTotalItemCount = totalItemCount;
            currentPage++;
        }

        // If it isn't currently loading, we check to see if we have breached
        // the visibleThreshold and need to reload more data.
        // If we do need to reload some more data, we execute onLoadMore to fetch the data.
        if (!loading && (firstVisibleItem + visibleItemCount + visibleThreshold) >= totalItemCount ) {
            loading = onLoadMore(currentPage + 1, totalItemCount);
        }
    }

    // Defines the process for actually loading more data based on page
    // Returns true if more data is being loaded; returns false if there is no more data to load.
    public abstract boolean onLoadMore(int page, int totalItemsCount);

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        // Don't take any action on changed
    }
}

我的适配器类就像地狱一样巨大(以显示所有UI),读取所有代码可能会造成混淆。 但是,假设您有一个普通的recyclerview适配器来处理字符串数组列表作为输入,请在您的答案中写下该内容,如果我本人必须在适配器中放入任何内容,以便无休止地滚动工作。

总体而言,即时通讯正在寻找针对此普遍问题的完整简便实用的解决方案。

谢谢!

您的方法似乎有点过于复杂。 根本不需要使用滚动侦听器。 我会采取另一种方法。

无限滚动器背后的主要思想是您将一部分项保留在内存中,因为获取所有项太昂贵了(在时间,内存等方面)。 取而代之的是获取并显示一个子集,然后当您看起来很快需要它们时,则获取其余部分。 可以说有1000个项目要显示。 您可能只想在开头显示前100个。 因此,当您认为要立即显示下一个100时,就可以开始提取。 像这样:

bindViewHolder(VH holder, int position) {
    if(position > getCount() - ITEM_FETCH_THRESHOLD && !fetching) {
        fetching = true;
        performFetch();
    }
}

performFetch应该启动异步提取。 提取完成后,应调用notifyDataSetChanged()。 ITEM_FETCH_THRESHOLD是一个常量,您可以使用它直到确定正确为止(正确的值应足够大,以便可以在结束之前完成提取,但应尽可能小以避免过度提取)。

这就是您进行无限滚动所需的全部。 您可以添加一些UI调整,以防用户在获取完成之前触底,但这些调整很简单。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM