Was ist der Lebenszyklus für den RecyclerView-Adapter?

Lesezeit: 4 Minuten

Ich fordere Bilder vom Presenter im Adapter an:

  @Override
  public void onBindViewHolder(SiteAdapter.ViewHolder holder, int position)
  {
    Site site = sites.get(position);
    holder.siteName.setText(site.getName());
    requestHolderLogo(holder, site.getLinks().getLogoUrl());
  }

  private void requestHolderLogo(final ViewHolder holder, final String logoUrl)
  {
    compositeSubscription.add(
      presenter.bitmap(logoUrl)
        .subscribe(
          bitmap -> {
            holder.siteLogo.setImageBitmap(bitmap);
            holder.siteLogo.setVisibility(View.VISIBLE);
          },
          error -> {
            holder.siteName.setVisibility(View.VISIBLE);
          })
    );
  }

Wann sollte ich mich abmelden? ViewHolder wird wiederverwendet. Es ist leicht.

Aber wie stoppen Sie alle Abonnements, wenn die Ansicht zerstört ist? Ich sollte wahrscheinlich auch die Presenter-Referenz annullieren, um Speicherverluste zu vermeiden

  • Bitte erklären Sie, warum Sie herabstimmen

    – Eugen Martynow

    7. Juni 2016 um 9:16 Uhr

  • Überprüfen Sie meine Antwort hier stackoverflow.com/a/68351804/6039240

    – Amr

    12. Juli 2021 um 17:43 Uhr

Benutzer-Avatar
Bartek Lipinski

Ich denke, der beste Weg, dies zu tun, wäre:

  1. Halte ein subscription Referenz in der SiteAdapter.ViewHolder
  2. unsubscribe das subscription Objekt hinein onBindViewHolder (Es heißt, wenn die ViewHolder wird wiederverwendet)
  3. Behalte das CompositeSubscription Objekt in Ihrem adapter
  4. Verwenden Sie die onDetachedFromRecyclerView Methode von dir Adapter zu unsubscribe das compositeSubscription

So:

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

    private CompositeSubscription compositeSubscription = new CompositeSubscription();

    // other needed SiteAdapter methods

    @Override
    public void onBindViewHolder(SiteAdapter.ViewHolder holder, int position) {
        if (holder.subscription != null && !holder.subscription.isUnsubscribed()) {
            compositeSubscription.remove(holder.subscription);
            // this will unsubscribe the subscription as well
        }
        Site site = sites.get(position);
        holder.siteName.setText(site.getName());
        requestHolderLogo(holder, site.getLinks().getLogoUrl());
    }

    private void requestHolderLogo(final SiteAdapter.ViewHolder holder, final String logoUrl) {
        holder.subscription = presenter.bitmap(logoUrl)
                .subscribe(
                        bitmap -> {
                            holder.siteLogo.setImageBitmap(bitmap);
                            holder.siteLogo.setVisibility(View.VISIBLE);
                        },
                        error -> {
                            holder.siteName.setVisibility(View.VISIBLE);
                        });
        compositeSubscription.add(holder.subscription);
    }

    @Override
    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        compositeSubscription.unsubscribe();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public Subscription subscription;

        // some holder-related stuff

        public ViewHolder(View itemView) {
            super(itemView);
            // init holder
        }
    }
}

  • Cool, also gibt es keine Methode auf dem Adapter, die wann aufgerufen wird RecyclerView ist losgelöst von der Aktivität

    – Eugen Martynow

    7. Juni 2016 um 9:25 Uhr

  • Nun… eigentlich gibt es einen – onDetachedFromRecyclerView und es könnte leicht was machen recycle() derzeit tut. Gute Idee 🙂

    – Bartek Lipinski

    7. Juni 2016 um 9:29 Uhr


  • onDetachedFromRecyclerView wird aufgerufen, wenn Sie Adapter wechseln, aber es wird nicht aufgerufen, wenn die Konfiguration geändert wird :/

    – Miha_x64

    24. Januar 2017 um 10:23 Uhr

  • @ Miha_x64, das scheint ein ganz anderes Problem zu sein

    – Bartek Lipinski

    24. Januar 2017 um 11:26 Uhr

  • Wie werden Sie dasselbe Problem lösen, wenn das Abonnement etwas ist, das ständig nach mehr Daten lauscht? Für den Kontext verwende ich den Firebase Data Change Listener.

    – Adi

    21. November 2018 um 21:37 Uhr

Benutzer-Avatar
eugstmann

Für andere, die das gleiche Problem haben: viewDetachedFromWindow im Adapter wird nur aufgerufen, wenn der Adapter in onPause (Aktivität, Fragment) oder onDetachFromWindow (Aktivität, Fragment) auf null gesetzt ist.

recyclerview.setAdapter(null)

Dann erhalten Sie viewDetachedFromWindow(…), wo Sie Ihre internen Zustände und Abonnements freigeben können. Ich würde Ihre Abonnements in Bindung einrichten, stellen Sie sicher, dass Sie vor jedem Bindungsanruf alte Abonnements freigeben, da eine Ansicht recycelt werden kann.

Eine andere Möglichkeit besteht darin, eine benutzerdefinierte Ansicht statt nur eines Layouts in Ihrer Fabrik aufzublasen. Dann können Sie die Bereinigung in der benutzerdefinierten Ansicht onDetachFromWindow() vornehmen. Sie erhalten das onDetachedFromWindow auch ohne den Adapter auf null zu setzen.

  • Wie werden Sie dasselbe Problem lösen, wenn das Abonnement etwas ist, das ständig nach mehr Daten lauscht? Für den Kontext verwende ich den Firebase Data Change Listener.

    – Adi

    21. November 2018 um 21:37 Uhr

  • @Adi Ich würde eine benutzerdefinierte Ansicht erstellen und onDetachFromWindow() verwenden

    – eugstmann

    26. November 2018 um 8:36 Uhr

  • Das würde das Problem glaube ich nicht lösen. onDetachFromWindow wird aufgerufen, wenn die Aktivität aktiv ist und eine Recycler-Ansicht aus dem Fenster gescrollt wird. Wenn Sie jedoch eine Aktivität schließen, wird diese Methode nicht für die zuletzt im Fenster sichtbaren Ansichten aufgerufen. Es würde also ein Speicherleck geben.

    – Adi

    27. November 2018 um 14:18 Uhr

  • @Adi onDetachFromWindow wird auch aufgerufen, wenn die Aktivität zerstört wird, beispielsweise wenn Sie die Android-Zurück-Taste drücken.

    – eugstmann

    29. November 2018 um 20:21 Uhr

  • So viele Stunden mit diesem Thema verschwendet. Vielen Dank.

    – Rubén Viguera

    6. Juni 2019 um 13:39 Uhr

Man kann anrufen public void onViewRecycled(@NonNull VH holder)
Geben Sie hier die Bildbeschreibung ein

1245090cookie-checkWas ist der Lebenszyklus für den RecyclerView-Adapter?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy