2017-11-11 6 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つのムービー(リクエストごとに指定された数)になります。私はこれがリストが成長し、記憶量が増えるからだと思う。記事では、確実に作業を継続するためにページネーションシステムのためには

に言及し、リスト

に新しいアイテムを追加する前にアイテムのアダプタをクリア(または配列をクリアした後、アダプタに通知)するようにしてください

は、あなたが戻ってまでスクロールするためallMoviesリストにリストの前のページを維持する必要はないでしょう

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

しかし、これに上記onNextの実装を変更するには、無限スクロールを壊しますか?同時に、無限のスクロールを使用すると、ページ数に応じてOOMが発生する可能性があります。

答えて

0

私はあなたのコードをあなたと共有できるので、私のリストがうまくいきます。

このメソッドを初めて使用すると、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(); 
} 

は、これらの変数は、次のAPI呼び出しのための開始位置を保持している

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

のようにそれを使用してください使用のインターフェース。

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