2015-02-24 8 views
5

Nella mia app di prova ho implementato uno Recyclerview. Attualmente raccolgo 5000 elementi di dati in un modello e carica la vista con questo elenco. Tutto è perfetto e funziona bene, ma non voglio caricare tutti i 5000 oggetti. Preferirei caricare 100 voci e una volta che l'utente ha toccato il fondo, caricare i successivi 100 e renderlo essenzialmente una lista in continua crescita.Possiedo un Recyclerview e un elenco con 5000 articoli ma voglio caricare solo 100 elementi alla volta

posso implementare onScrollListener contro il Recyclerview di fare la rilevazione di quando ho raggiunto la fine, ma il mio problema (semplice come questo suona) è, qual è il modo migliore per raccontare la Recyclerview di caricare solo 100 fino a quando ho dire?

mio adattatore:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { 

    private List<ImageFeed> mFeedList; 

    public MyAdapter(List<ImageFeed> feedList) { 
     this.mFeedList = feedList; 
    } 

    public void setFeedList(List<ImageFeed> feedList) { 
     mFeedList = feedList; 
    } 

    @Override 
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup vGroup, int i) { 
     View v = LayoutInflater.from(vGroup.getContext()).inflate(R.layout.recycler_list, vGroup, false); 
     return new MyAdapter.ViewHolder(v); 
    } 

    @Override 
    public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, int i) { 
     String mTitle = mFeedList.get(i).getTitle(); 

     ...//Do other stuff 
    } 

    @Override 
    public int getItemCount() { 
     return mFeedList.size(); 
    } 

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 

     protected ImageView mImageView; 
     protected TextView mTitle; 
     protected ProgressBar mLoader; 
     private int mItemId; 

     public ViewHolder(View itemView) { 
      super(itemView); 
      this.mImageView = (ImageView) itemView.findViewById(R.id.imgItem); 
      this.mTitle = (TextView) itemView.findViewById(R.id.txtTitle); 
      this.mLoader = (ProgressBar) itemView.findViewById(R.id.mLoaderProgress); 

      this.mImageView.setOnClickListener(this); 
      itemView.setOnClickListener(this); 
     } 

     public void setItem(int item) { 
      this.mItemId = item; 
     } 

     @Override 
     public void onClick(View v) { 
      if (v instanceof ImageView) { 
       Toast.makeText(v.getContext(), "Image view clicked: " + this.mItemId, Toast.LENGTH_SHORT).show(); 
      } else { 
       Toast.makeText(v.getContext(), this.mItemId + " ", Toast.LENGTH_SHORT).show(); 
      } 
     } 
    } 
} 

Pensando lo scenario fuori avrei pensato che passa una lista più piccola è una possibilità, ma non si sente completamente a destra.

+0

sì, è in realtà un modello * comune *. Forse potresti iniziare a precaricarlo quando sei x elementi lontano dal fondo – Blackbelt

+0

Potrei essere fraintendere la domanda, ma questo non sembra specifico per RecyclerView. Se hai già fatto il lavoro di caricare 5.000 articoli, hai già fatto il lavoro pesante. In caso contrario, penso che tu sia sulla strada giusta implementando onScrollListener e semplicemente caricando le pagine successive di dati quando un utente raggiunge il fondo. –

+0

È un problema comune, ma non conosco una soluzione comune/semplice. Il concetto di adattatore standard non ha incluso nulla che indichi quale parte del modello di supporto è richiesta o attualmente visualizzata. È solo per "adattarsi" dai dati * caricati * agli elementi visualizzati. Potresti risolvere per es. implementando il caricamento automatico tramite gli ascoltatori di scroll o gli oggetti speciali che vengono visualizzati (una voce di elenco che dice "caricamento ..") attivano il caricamento, l'impaginazione manuale tramite pulsanti/scorrimento/... o anche visualizzando elementi fittizi mentre caricano in modo asincrono gli oggetti effettivi (i caricatori di immagini fanno quel genere di cose). – zapl

risposta

6

Ok, quindi questo non è stato particolarmente difficile, dopo tutto - credo che il mio problema principale era finita pensando allo scenario ...

Quindi la prima cosa che faccio è ottenere i dati appropriati (in questo caso attraverso JSON) e memorizzarlo in un array JSON per la manipolazione successiva - attualmente sto ancora ricevendo il set completo (Ie 5000) ma è facilmente modificabile.

Questo viene eseguito tramite un AsyncTask con una barra di avanzamento indeterminata. Una volta completato, analizzo solo il JSON in 20 elementi e lo carico nell'adattatore.

Una volta fatto ho la mia Recyclerview.onScrollListener ....

mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { 

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

       mOnScreenItems = mRecyclerView.getChildCount(); 
       mTotalItemsInList = llm.getItemCount(); 
       mFirstVisibleItem = llm.findFirstVisibleItemPosition(); 

       if (mLoadingItems) { 
        if (mTotalItemsInList > mPreviousTotal) { 
         mLoadingItems = false; 
         mPreviousTotal = mTotalItemsInList; 
        } 
       } 

       if (!mLoadingItems && (mTotalItemsInList - mOnScreenItems) <= (mFirstVisibleItem + mVisibleThreshold)) { 
        new AsyncLoadTask().execute(); 
        mLoadingItems = true; 
       } 
      } 

      @Override 
      public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 
       super.onScrollStateChanged(recyclerView, newState); 
      } 

     }); 

Quando si avvicina alla fine o tocca il fondo di una nuova AsynTask viene dato il via per caricare elementi aggiuntivi nella lista. Lo onPostExecute() quindi aggiorna l'adattatore tramite il suo metodo mMyAdapter.notifyDataSetChanged(); risultando in un buon aggiornamento senza problemi. Un sacco di pulizia da fare, ma le basi sono lì.

Grazie per la direzione ragazzi!

+0

bel ragazzo. Tuttavia ho dovuto fare una cosa in più. Invece di usare mMyAdapter.notifyDataSetChanged(); Ho usato mMyAdapter.notifyItemInserted (posizione); In questo modo l'adattatore non occuperebbe memoria per gli elementi già caricati. – neaGaze

Problemi correlati