2015-08-27 9 views
19

Vor der API 23 habe ich die onAttach-Methoden von Fragments verwendet, um meine Listener-Instanz abzurufen, dann wird die Referenz in onDetach bereinigt. ex:onAttach (Aktivität) veraltet: Hier kann ich prüfen, ob die Aktivität die Callback-Schnittstelle implementiert

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    mListener = null; 
    try { 
     mListener = (SellFragmentListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() 
       + " must implement SellFragmentListener"); 
    } 
} 

@Override 
public void onDetach() { 
    super.onDetach(); 
    mListener = null; 
} 

Ist es sicher, die gleiche Prüfung innerhalb onAttach (Context Kontext) oder gibt es eine bessere Art und Weise zu tun, um die Halter Aktivitätsinstanz zu bekommen?

+0

'onActivityCreated'? – mbmc

+0

Normalerweise mache ich diese Art von Ding auf 'onResume()'/'onPause()', besonders wenn der Listener alles tut, was die UI betrifft. –

+0

@tibo Ich denke, dass onActivityCreated nicht aufgerufen wird, wenn ein Fragment zu einer bestehenden Aktivität hinzugefügt wird. –

Antwort

23

Überprüfen Sie den Quellcode:

/** 
* Called when a fragment is first attached to its context. 
* {@link #onCreate(Bundle)} will be called after this. 
*/ 
public void onAttach(Context context) { 
    mCalled = true; 
    final Activity hostActivity = mHost == null ? null : mHost.getActivity(); 
    if (hostActivity != null) { 
     mCalled = false; 
     onAttach(hostActivity); 
    } 
} 

/** 
* @deprecated Use {@link #onAttach(Context)} instead. 
*/ 
@Deprecated 
public void onAttach(Activity activity) { 
    mCalled = true; 
} 

So ist die onAttach(Activity activity) durch die onAttach(Context context) genannt wird, wenn es eine Host-Aktivität ist. Sie können die onAttach(Activity activity) sicher verwenden.

+0

Dies ist die richtige Antwort –

+0

mHost ist nicht zugänglich von außerhalb des Pakets ... Also was dann? – russellhoff

4

Nun, was veraltet ist, ist onAttach(Activity activity); Methode, aber der gesamte Fluss bleibt. also machst du nichts wirklich, da onAttach(Activity activity); noch lange genug unterstützt wird.

3

Ich musste noch nie onAttach(Context context) verwenden, aber ich denke, dass Ihr Code grundsätzlich gut ist. So, hier ist mein Vorschlag, mit Ihrem Code:

public void onAttach (Context context) { 
    super.onAttach(context); 
    try { 
     Activity activity = (Activity) context; 
     mListener = (SellFragmentListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() 
       + " must implement SellFragmentListener"); 
    } 
} 

Der wesentliche Unterschied ist, dass ich context typisieren kann die Aktivität zu erhalten. Dies liegt daran, dass sich Context auf die Unterklasse propagieren kann, die die Aktivität darstellt.

Ein weiteres Problem, API 23 ist noch weit weg von uns, um uns Sorgen zu machen. Wenn Sie sich Sorgen machen, ist die Verwendung von Build-Pragma (statisches Build) eine gute Option.

+1

Sie sollten Kontext direkt umwandeln. Oder wenn der Kontext eine Instanz einer Aktivität sein soll. Überprüfe das zuerst mit if (context instanceof Activity) {...} – Daverix

+0

@Daverix, Interessanter Kommentar "Du solltest den Kontext direkt umwandeln". Bitte sei spezifischer. Wollen Sie sagen, Objektkontext kann/sollte direkt in mlistener umgewandelt werden? Das wird den Code von 2 Zeilen auf nur 1 Zeile reduzieren. Wenn das der Fall ist, ist das nur ein Unterschied im Codierungsstil. –

+0

Ja, das mag ein Unterschied im Codierungsstil sein, aber immer noch eine unnötige Zeile imo. Andernfalls ist es besser "instanceof" zu verwenden, anstatt ClassCastExceptions zu erfassen. Aber am Ende spart Ihnen das vielleicht nur ein bisschen mehr Linien und Sie erhalten eine minimale Leistung. – Daverix

0

Ich habe die gleiche Situation konfrontiert. Ich habe verschiedene Beiträge gelesen und schließlich meinen Code im onCreate() - Fragmentblock implementiert. Bis jetzt habe ich kein Problem gesehen und ich denke, dass dies kein Problem wäre, da onCreate sofort nach onAttach im Lebenszyklus aufgerufen wird.

@Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     try { 
      listnener = (TilesOnClickListnener)getActivity(); 
     } catch (ClassCastException e) { 
      throw new ClassCastException(getActivity().toString() + " must implement OnArticleSelectedListener"); 
     } 
    } 
+0

Außerdem habe ich vergessen zu erwähnen, dass der Casting-Kontext zu Activity nicht gut für mich lief. –

+0

Warum würde Activity Casting nicht gut funktionieren? Funktioniert gut für mich, wenn Sie Aktivität außerhalb des try/catch-Blocks deklarieren --- public void onAttach (Kontextkontext) {super.onAttach (Kontext); Aktivität Aktivität = (Aktivität) Kontext; versuch die Aktivität {mListener = (SellFragmentListener); } catch (ClassCastException e) {neue ClassCastException werfen (activity.toString() + "muss SellFragmentListener implementieren"); }} – WallyHale

+0

Großartig! wenn es funktioniert. Ich habe das nicht versucht. Danke für die Information. –

2

Wie in Zsolt Mester Antwort gezeigt, ist onAttach(Activity activity) für onAttach(Context context) veraltet. Sie müssen also nur prüfen, ob der Kontext eine Aktivität ist.

In Android Studio, wenn Sie zu gehen Datei> Neu> Fragment, können Sie den automatisch generierten Code, der die richtige Syntax enthalten wird.

import android.support.v4.app.Fragment; 
... 

public class MyFragment extends Fragment { 

    private OnFragmentInteractionListener mListener; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // inflate fragment layout 
     return inflater.inflate(R.layout.fragment_myfragment, container, false); 
    } 

    @Override 
    public void onAttach(Context context) { 
     super.onAttach(context); 
     if (context instanceof OnFragmentInteractionListener) { 
      mListener = (OnFragmentInteractionListener) context; 
     } else { 
      throw new RuntimeException(context.toString() 
        + " must implement OnFragmentInteractionListener"); 
     } 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     mListener = null; 
    } 

    public interface OnFragmentInteractionListener { 
     // TODO: Update argument type and name 
     void onFragmentInteraction(Uri uri); 
    } 
} 

Hinweise

  • Da die Mutter Aktivität unserer OnFragmentInteractionListener (die willkürlich benannte Schnittstelle) implementieren muss, sorgt für (context instanceof OnFragmentInteractionListener) Überprüfung, dass der Kontext tatsächlich die Aktivität ist.

  • Beachten Sie, dass wir die Support-Bibliothek verwenden. Ansonsten würde onAttach(Context context) nicht von Pre API 23 Versionen von Android aufgerufen werden.

Siehe auch

0
public class MainActivity extends AppCompatActivity implements topsection.TopSectionListener { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
} 



public void createMeme(String top, String bottom){ 
    bottomsection fragmentbottom = (bottomsection) getSupportFragmentManager().findFragmentById(R.id.fragment2); 
    fragmentbottom.setMemeText(top, bottom); 
    } 
} 
0

Ich benutze die native Fragment statt der one from the Support Library. Ich habe beide onAttach() Methoden in meinem Code und führte einige Debugging auf Geräten mit verschiedenen SDK-Versionen. Ich fand das:

SDK 22 und unter - nur onAttach(Activity) heißt. Nicht wirklich überraschend, weil onAttach(Context) wurde nur in SDK eingeführt 23.

SDK 23 und über-onAttach(Context) zuerst und dannonAttach(Activity) genannt. (Dies steht im Einklang mit dem, was @Zsolt Mester sagte über den Quellcode in einer anderen Antwort auf dieses Thema.)

Seit minSdkVersion für meinen app unter 23 war ich gerade beschlossen onAttach(Context) ganz zu verzichten und einfach fügen Sie die @SuppressWarnings("deprecation") Anmerkung zu meinem bestehenden onAttach(Activity) Methode.

Verwandte Themen