2017-11-11 181 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