2017-11-11 108 views
1

我阅读本指南实施endless scrolling并尝试过。这里是我的loadNextDataFromApi实现:recyclerview无尽滚动放缓

public void loadNextDataFromApi(int page, String term) { 
    movieService.getMovies(page, term) 
      .subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(new Observer<List<Movie>>() { 
       @Override 
       public void onCompleted() { 

       } 

       @Override 
       public void onError(Throwable e) { 

       } 

       @Override 
       public void onNext(List<Movie> currentPageMovies) { 
        int start = allMovies.size(); 
        allMovies.addAll(currentPageMovies); 
        adapter.notifyItemRangeInserted(start, currentPageMovies.size()); 
       } 
      }); 
} 

allMovies保存给定搜索的所有电影。这最初工作正常,但滚动最终加载较慢,从平滑滚动到一次3个电影(每个请求指定的数量)。我认为这是因为列表增长并占用越来越多的内存。文中提到,

为了使分页系统继续工作可靠,你应该确保清除项目的适配器(或清除阵列之后通知适配器)追加新项目到列表

但改变onNext实现上述这打破了无尽的滚动:

  @Override 
      public void onNext(List<Movie> currentPageMovies) { 
       allMovies.clear(); 
       adapter.notifyDataSetChanged(); 
       int start = allMovies.size(); 
       allMovies.addAll(currentPageMovies); 
       adapter.notifyItemRangeInserted(start, currentPageMovies.size()); 
      } 

难道你需要保持在allMovies名单列表的前几页滚动备份?同时这样做与无尽的滚动可以导致OOM取决于页数

回答

0

我一直致力于无尽滚动API调用,所以我可以与我分享我的代码,因为我发现我的列表做得很好。

首先使用此方法让recyclerview达到最后位置。

public void setRecyclerViewLastPositionListner(RecyclerView rv, final LinearLayoutManager mLayoutManager, final OnLastPositionReached onLastPositionReached) { 
    rv.addOnScrollListener(new RecyclerView.OnScrollListener() { 
     @Override 
     public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 
      super.onScrollStateChanged(recyclerView, newState); 
      if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { 
       userScrolled = true; 
      } 
     } 

     @Override 
     public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 

      super.onScrolled(recyclerView, dx, dy); 
      // Here get the child count, item count and visibleitems 
      // from layout manager 

      visibleItemCount = mLayoutManager.getChildCount(); 
      totalItemCount = mLayoutManager.getItemCount(); 
      pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition(); 

      // Now check if userScrolled is true and also check if 
      // the item is end then update recycler view and set 
      // userScrolled to false 
      if (userScrolled && (visibleItemCount + pastVisiblesItems) == totalItemCount) { 
       userScrolled = false; 
       if (onLastPositionReached != null) onLastPositionReached.onReached(); 
      } 
     } 
    }); 
} 

这里使用的接口

public interface OnLastPositionReached { 
    void onReached(); 
} 

使用它像

UtilitiesV2.getInstance().setRecyclerViewLastPositionListner(yourRecyclerView, mLayoutManager, new UtilitiesV2.OnLastPositionReached() { 
      @Override 
      public void onReached() { 
       callEBookApi(); 
      } 
     }); 

这些变量持有启动下一个API调用的位置。

long start = 0; 
    private int lastReceivedListSize = 0; 
     int DEFAULT_LIMIT = 20; 

考虑在这里调用你的api。

private void callEBookApi() { 
     start = booksAdapter.getItemCount(); 
     if (start != 0 & lastReceivedListSize < DEFAULT_LIMIT) 
      return; 
     BeanLimit beanLimit = new BeanLimit(); 
     beanLimit.setLimit(DEFAULT_LIMIT); 
     beanLimit.setStartpoint(start); 
     showProgressBar(); 
     try { 
      callWebServicePost(Interactor.RequestCode_getEbooks, Interactor.Tag_getEbooks, Interactor.Method_getEbooks, new JSONObject(new Gson().toJson(beanLimit)), false, new OnResponseListener() { 
       @Override 
       public void onSuccess(int requestCode, Response responsePacket) { 

        hideProgressBar(); 

         ArrayList<BookBean> list = responsePacket.getResponsePacket().getBooksList(); 
         lastReceivedListSize = list.size(); 
         updateListData(list); 

       } 

       @Override 
       public void onError(int requestCode, ErrorType errorType) { 
        FragmentEbooks.super.onError(requestCode, errorType); 
        hideProgressBar(); 
        UtilProject.getInstance().showNothingToDisplayLayout(FragmentEbooks.this); 
       } 
      }); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
      hideProgressBar(); 
     } 
    } 




    private void updateListData(ArrayList<BookBean> list) { 
     if (list == null) listBooks = new ArrayList<>(); 
     booksAdapter.insertItemsInList(list); 
     if (booksAdapter.getList().size() != 0) { 
      // UtilProject.getInstance().hideNothingToDisplayAndProgressBar(this); /*here you show placeholder if list empty*/ 
     } else { 
      // UtilProject.getInstance().showNothingToDisplayLayout(this); 
     } 
    } 





    public void insertItemsInList(ArrayList<InvitationBean> myList) { 
     if (list == null) list = new ArrayList<>(); 
     int lastIndex = list.size(); 
     list.addAll(myList); 
     notifyItemRangeInserted(lastIndex, myList.size()); /*use this line for smooth scrolling if you use notifyDataSetChanged it will load all data again*/ 
//  notifyDataSetChanged(); 
    } 

希望这可以帮助你。

+0

谢谢你,但你仍然不断追加查询结果到更大的列表,就像在我发布的解决方案。你最终会得到一个OOM异常和加载速度减慢 – Marc

+0

所以你想在该列表对象的解决方案一次只有最多100个项目。它会随着滚动而变老。 我认为你可以管理它。 如果你喜欢这样做,你可以管理一个数据库(如糖),在其中存储你的列表,你可以从数据库中获取数据并加载。 你可以做到男人。 – Khemraj