2012-10-15 4 views
19

Die Android-Dokumentation schlägt vor, dass das Fragment, um von einer Aktivität zu einem gehosteten Fragment zu kommunizieren, eine Callback-Schnittstelle definieren kann und dass die Host-Aktivität es implementieren muss. Das Grundmuster beinhaltet die Implementierung von onAttach in Ihrem Fragment und die Umwandlung der Aktivität in eine Callback-Schnittstelle. Siehe http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity.Ist es vorzuziehen, Activity.onAttachFragment oder Fragment.onAttach zu verwenden, um zwischen einer Aktivität und einem verschachtelten Fragment zu kommunizieren?

Hier ist ein Beispiel für die Bereitstellung eines Fragments einige Initialisierungsdaten sowie das Abhören eines Navigationsrückrufs.

public class HostActivity extends Activity implements FragmentHost { 
    @Override 
    UiModel getUiModel() { 
    return mUiModel; 
    } 
    @Override 
    FragmentNavListener getNavListener() { 
    return mNavListener; 
    } 
... 
} 

public class HostedFragment extends Fragment { 
    @Override 
    public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    if (activity instanceof FragmentHost) { 
     FragmentHost host = (FragmentHost) activity; 
     setUiModel(host.getUiModel()); 
     setNavListener(host.getFragmentNavListener()); 
    } 
    } 
    ... 
} 

Vergleichen Sie dies onAttachFragment in der Host-Aktivität zu verwenden ausdrücklich das Fragment zu initialisieren:

public class HostActivity extends Activity { 
    @Override 
    public void onAttachFragment(Fragment fragment) { 
    super.onAttachFragment(fragment); 
    if (fragment instanceof HostedFragment) { 
     HostedFragment hostedFragment = ((HostFragment) fragment); 
     hostedFragment.setUiModel(mUiModel); 
     hostedFragment.setNavListener(mNavListener); 
    } 
    } 
    ... 
} 

Für mich ist es wie das erste Muster scheint hat einige Nachteile:

  1. Es macht das Fragment, das aus verschiedenen Aktivitäten schwieriger zu verwenden ist, seit , da alle diese Aktivitäten die erforderliche Schnittstelle implementieren müssen. Ich kann mir Fälle vorstellen, in denen eine bestimmte Fragment-Instanz nicht vollständig von der Host-Aktivität konfiguriert werden muss, aber alle möglichen Host-Aktivitäten die Host-Schnittstelle implementieren müssen.
  2. Es macht den Code etwas schwieriger für jemanden zu folgen, der nicht mit dem verwendeten Muster vertraut ist. Das Initialisieren des Fragments in onFragmentAttached scheint einfacher zu folgen, da der Initialisierungscode in der gleichen Klasse lebt, in der das Fragment erstellt wird.
  3. Unit-Tests eine Bibliothek wie Robolectric wird schwieriger, da beim Aufruf onAttach verwenden, müssen Sie jetzt FragmentHost implementieren, anstatt nur onAttach (neue Aktivitäten() aufrufen.

Für diejenigen unter Ihnen, die Aktivität getan haben Fragment Kommunikation, welche Muster finden Sie bevorzugt und warum? gibt es Nachteile onAttachFragment von der Host-Aktivität zu verwenden?

Antwort

6

ich kann nicht persönlich in Bezug auf Tests sprechen, aber es gibt Alternativen zu Fragmente/Aktivität Callback-Schnittstelle Kommunikation.

Für ex Sie können einen Event-Bus verwenden, um die Fragmente und Ihre Aktivität zu entkoppeln. Ein hervorragendes Ereignis Bus ist hier zu finden:

Otto - An event Bus by Square

Es wird aktiv von einigen sehr talentierten Ingenieuren Platz entwickelt. Sie können auch den LocalBroadcastManager verwenden, der in der Android-Supportbibliothek enthalten ist.

LocalBroadcastManager

Eric Burke von Platz hat eine Präsentation, wo er beide erwähnt, die hier gefunden werden kann:

Android App Anatomy

+0

Otto ist jetzt veraltet – Louis

2

ich das Fragment.onAttach(...) Muster in meinem letzten Projekt verwendet haben.Ich sehe zwei Vorteile:

  1. Sie können frühzeitig prüfen, ob die Hosting-Aktivität die erforderliche Schnittstelle implementiert und eine Ausnahme auslösen, wenn nicht
  2. gibt es weniger Risiko von dem gastgebenden Kontext auf eine Referenzhalt nachdem das Fragment gelöst wurde

um von 2. zu nehmen, Sie Verweise auf UiModel und NavListener nicht speichern müssen, wie Sie in Ihrem Codebeispiel tun. Wenn Sie mit diesen Instanzen interagieren möchten, sollten Sie stattdessen Code wie ((FragmentHost) getActivity).getNavListener().onNav(this) oder alternativ ((FragmentHost) getActivity).onNav(this) verwenden. Sie könnten den Fragment-Host in einem Feld speichern, das Sie in onDetach(...) als Mittelgrundmethode auf Null setzen, wenn Sie das konstante Casting vermeiden möchten.

Ich stimme zu, dass die Initialisierung eines Fragments aus der Aktivität, die es erstellt, intuitiver scheint.

Nachdem ich all das gesagt habe, werde ich Fragmente in meinem aktuellen Projekt komplett überspringen. Der folgende Beitrag spiegelt die Lehren aus meiner letzten ziemlich gut wieder: https://corner.squareup.com/2014/10/advocating-against-android-fragments.html

Verwandte Themen