[英]Android TV - How to implement endless RecyclerView like with Leanback HorizontalGridView
[英]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.