webentwicklung-frage-antwort-db.com.de

Wie kann RecyclerView das Recycling definierter Positionen stoppen?

Mein Problem ist: Ich habe ein Video-Streaming in einer der Ansichten in RecyclerView.

Wenn der Benutzer einen Bildlauf durchführt, wird die Ansicht wiederverwendet und andere Kameras starten ihr eigenes Streaming für diesen wiederverwendeten Ansichtsinhaber. Dies ist schlecht für die Benutzeroberfläche, da der Streaming-Vorgang einige Sekunden dauert.

Wie kann ich zu RecyclerView sagen: "Hey Recycler, bitte recyceln Sie nicht genau diese Position x und geben Sie diese Position IMMER derselbe Ansichtsinhaber, den Sie ihm zum ersten Mal gegeben haben, anstelle eines zufälligen "?

Bitte jemand hilft mir = (

19
Daniel Oliveira

Weisen Sie in Ihrer getItemViewType(int position) - Methode des Adapters jedem Video eindeutige Werte zu, sodass für dasselbe Video immer derselbe ViewHolder zurückgegeben wird, den Sie möchten.

  • gibt für jeden Videotyp eine eindeutige positive Zahl als Typ zurück (hier habe ich die Adapterposition als eindeutigen Schlüssel verwendet)
  • rückgabe negativer Zahlen für alle Nicht-Video-Elemente. (hier nichts Besonderes, nur um Konflikte mit Videoelementen zu vermeiden, verwenden wir negative Zahlen für Nicht-Videoelemente.)

Ich hoffe du kommst auf die Idee. Prost :)

    @Override
    public int getItemViewType(int position) {
        // Just as an example, return 0 or 2 depending on position
        // Note that unlike in ListView adapters, types don't have to be   contiguous
        if(dataList.get(position).isVideo()){
            return position;

        }else{
            return -1;//indicates general type, if you have more types other than video, you can use -1,-2,-3 and so on.
        }
    }

 @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         switch (viewType) {
             case -1:  View view1 = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.general_item, parent, false);
                     return new GeneralViewHolder(view1);
             default:View view2 = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.video_item, parent, false);
                     return new VideoViewHolder(view2);

         }
    }
14
Darish

Führen Sie viewHolder.setIsRecyclable(false) für das ViewHolder aus, das nicht recycelt werden soll.

From docs of ViewHolder # setIsRecyclable (boolean) :

Informiert den Recycler, ob dieser Artikel recycelt werden kann. Ansichten, die nicht wiederverwendbar sind, werden erst für andere Elemente wiederverwendet, wenn setIsRecyclable () später auf true festgelegt wird.

Dadurch wird nur ein ViewHolder erstellt.

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    ...
    @Override
    public void onViewAttachedToWindow(final RecyclerView.ViewHolder holder) {
        if (holder instanceof VideoViewHolder) {
            holder.setIsRecyclable(false);
        }
        super.onViewAttachedToWindow(holder);
    }

    @Override
    public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder) {
        if (holder instanceof VideoViewHolder){
            holder.setIsRecyclable(true);
        }
        super.onViewDetachedFromWindow(holder);
    }
    ...
}
12
azizbekian

RecyclerView verwendet eine Ansicht mehrmals, wenn sie die Liste enthält, die nicht gleichzeitig auf dem Bildschirm angezeigt wird (bedeutet, dass eine Liste eine große Menge von Elementen enthält, die nicht gleichzeitig auf dem Bildschirm angezeigt werden, wenn Sie nach oben und unten scrollen müssen). Wenn Benutzer durch die Liste scrollen, werden die Offscreen-Elemente wiederverwendet, um die verbleibenden Listenelemente anzuzeigen, die als Recycling bezeichnet werden.

Um das Recycling der Elemente zu beenden, rufen Sie diese Methode in Ihrer onBindViewHolder-Methode auf:

viewHolder.setIsRecyclable(false);

Diese Anweisung beendet das Recycling der Ansichten.

Um mit dem Recycling der Elemente zu beginnen, rufen Sie diese Methode in Ihrer onBindViewHolder-Methode auf:

viewHolder.setIsRecyclable(true);

Ich hoffe, dass dies Ihr Problem lösen wird. Vielen Dank

3
Aman Goyal

Ihr Problem liegt beim Betrachter. Ansichtsinhaber verweisen auf Ansichten, der Adapter nicht. Der Adapter speichert nur die Datenerfassung. Fügen Sie dem Ansichtshalter also ein Feld hinzu, um eine Referenz des Datenelements beizubehalten, das Sie zum Auffüllen der Ansicht im Ansichtshalter verwendet haben. Mit anderen Worten:

public class SomeViewHolder extends RecyclerView.ViewHolder{

    private View view;
    private Data data;

    public SomeViewHolder(View itemView) {
        super(itemView);
        view = itemView;
    }

    public void bindData(Data data){
        view.setData(data);
        this.data = data;
    }

    public void setData(Data data){
       this.data = data;
    }


    public Data getData(){
        return data;
    }

    public View getView(){
        return view;
    }
}

Jetzt weiß der Betrachter, welches Element des Adapters verwendet wird. Wenn Sie die Bindungsmethode im Adapter überschreiben, können Sie daher überprüfen, ob der Inhaber bereits eine Bindung zu bestimmten Daten hergestellt hat. Wenn die Daten Video enthalten, können Sie die Bindung vermeiden und eine bereits geladene Ansicht erzwingen.

@Override
public void onBindViewHolder(SomeViewHolder holder, int position) {

    //videoViewData is a data field you have to put into the adapter.
    //videoView is a view field you have to put into the adapter.

    if(adapterData.get(position).equals(videoViewData)){
        holder.setView(videoView);
        holder.setData(adapterData.get(position));
    }else{
        holder.bindData(adapterData.get(position));
        if(adapterData.get(position).isVideo()){
            videoViewData = adapterData.get(position);
            videoView = holder.getView(); 
        }
    }

}

Schließlich müssen Sie die onViewRecycled-Methode im Adapter überschreiben. Wenn also eine Ansicht mit einem Video wiederverwendet wird, können Sie die Ansicht abrufen und an einer anderen Stelle ablegen.

public void onViewRecycled(SomeViewHolder holder){
    if(holder.getData().isVideo()){
        videoViewData = holder.getData().
        videoView = holder.getView();
        videoView.pauseVideo();
    }
}

beachten Sie, dass dies zu ernsthaften Lecks führen kann, wenn Sie die gespeicherte Ansicht nicht verwalten. Außerdem müssen Sie Methoden definieren, mit denen Sie feststellen können, wann es sich bei Ihren Daten um Video handelt, und eine richtig definierte Methode, die der Methode entspricht.

2
Fco P.

Die beste Möglichkeit, Artikel zu handhaben, die nicht im Recycling-Überblick enthalten sind. Diese Antwort behebt Ihr Problem.

Artikel nicht recyceln

0
Ness Tyagi

Versuchen Sie, dies für diese bestimmte Position zu verwenden:

 holder.setIsRecyclable(false);

Hoffe das könnte helfen.

0