实施无尽的recyclerview -android?

时间:2017-04-24 01:08:29

标签: android android-layout 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适配器来处理一个字符串的arraylist作为输入,如果有什么我自己必须放在我的适配器中,请在你的答案中写下来,以便无休止地滚动工作。

总的来说,我正在为这个普遍问题寻找一个完整简单而实用的解决方案。

谢谢!

1 个答案:

答案 0 :(得分:1)

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

无限卷轴背后的主要思想是你在内存中保存了一个项目的子集,因为获取所有这些项目太昂贵(时间,内存等)。相反,你获取并显示一个子集,然后当你看起来很快就需要它们时,你会获取其余部分。让我们说要显示1000个项目。您可能只想在开头显示前100个。因此,当您认为您希望很快显示下一个100时,您就会开始获取。像这样:

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

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

所有你需要做的无限滚动。如果用户在获取完成之前点击底部,您可以添加一些UI调整,但这些调整很容易添加。