2015-02-24 2 views
5

Ich habe eine Recyclerview in meiner Test App implementiert. Momentan ziehe ich 5000 Daten in ein Modell und lade meine Ansicht mit dieser Liste. Alles ist großartig und funktioniert gut, aber ich möchte nicht alle 5000 Elemente laden. Ich würde es vorziehen, 100 Elemente zu laden, und sobald der Benutzer den Boden erreicht, laden Sie die nächsten 100 und machen es im Grunde zu einer ständig wachsenden Liste.Ich habe eine Recyclerview und eine Liste mit 5000 Artikeln, aber ich möchte nur 100 Artikel auf einmal laden

Ich kann onScrollListener gegen die Recyclerview implementieren, um die Erkennung von tun, wenn ich das Ende, aber meine Frage erreicht haben (so einfach wie das klingt) ist, was der beste Weg ist, um die Recyclerview zu sagen, nur 100 bis ich laden sagen?

Mein Adapter:

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(); 
      } 
     } 
    } 
} 

Denken das Szenario aus ich hätte gedacht, eine kleinere Liste vorbei ist eine Möglichkeit, aber es fühlt sich nicht ganz richtig.

+0

ja, es ist eigentlich ein gemeinsames * Muster *. Vielleicht könntest du damit beginnen, es vorher zu laden, wenn du x Elemente weit vom Boden entfernst – Blackbelt

+0

Ich könnte die Frage missverstehen, aber das scheint RecyclerView nicht spezifisch zu sein. Wenn Sie bereits 5000 Gegenstände geladen haben, haben Sie bereits das schwere Heben erledigt. Wenn nicht, denke ich, dass Sie auf dem richtigen Weg sind, indem Sie den onScrollListener implementieren und einfach nachfolgende Seiten von Daten laden, wenn ein Benutzer den Boden erreicht. –

+0

Es ist ein häufiges Problem, aber ich kenne keine gemeinsame/einfache Lösung. Das Standard-Adapterkonzept enthält nichts, das Ihnen sagen würde, welcher Teil des Backing-Modells benötigt wird oder aktuell angezeigt wird. Es dient nur zum "Anpassen" von * geladenen * Daten an angezeigte Elemente. Sie könnten z.B. durch das automatische Laden von Dateien über Scroll-Listener oder spezielle Elemente, die, wenn sie angezeigt werden (ein Listenelement mit dem Namen "loading .."), Laden, manuelles Paging über Schaltflächen/Streichen/.. oder sogar durch Anzeigen von Dummy-Elementen beim asynchronen Laden der tatsächlichen Elemente auslösen (Bildlader machen so etwas). – zapl

Antwort

6

Ok so dass diese nicht besonders schwierig war, nachdem alle - ich meine Hauptfrage denken über das Szenario dachte ...

Das erste, was ich tun ist, um die entsprechenden Daten erhalten (in diesem Fall durch JSON) und speichern Sie es in einem JSON-Array für die Manipulation später - derzeit bekomme ich immer noch den vollen Satz (Ie 5000), aber das ist leicht veränderbar.

Dies geschieht über eine AsyncTask mit einem unbestimmten Fortschrittsbalken. Sobald es fertig ist, analysiere ich das JSON nur auf 20 Elemente und lade dieses in den Adapter.

Einmal getan, was ich meine Recyclerview.onScrollListener haben ....

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); 
      } 

     }); 

Wenn das Ende naht oder trifft den Boden ein neues AsynTask getreten ist aus weitere Einträge in die Liste zu laden. Die onPostExecute() aktualisiert dann den Adapter über seine mMyAdapter.notifyDataSetChanged();-Methode, was zu einem reibungslosen Update führt. Viele Aufräumarbeiten, aber die Grundlagen sind da.

Danke für die Richtung Jungs!

+0

nett ein Typ. Allerdings musste ich eine Sache extra machen. Anstatt mMyAdapter.notifyDataSetChanged(); Ich habe mMyAdapter.notifyItemInserted (position); Auf diese Weise würde der Adapter keinen Speicher für bereits geladene Elemente belegen. – neaGaze

Verwandte Themen