Ich habe ein Fragment (F1) mit einer öffentlichen Methode wie dieser
public void asd() {
if (getActivity() == null) {
Log.d("yes","it is null");
}
}
und ja, wenn ich es nenne (aus der Aktivität), ist es null ...
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
F1 f1 = new F1();
transaction1.replace(R.id.upperPart, f1);
transaction1.commit();
f1.asd();
Es muss etwas sein, was ich sehr falsch mache, aber ich weiß nicht, was das ist
getActivity()
. Wie instanziieren Sie das Fragment? Hast du es in deiner layout.xml?Antworten:
commit
Plant die Transaktion, dh sie geschieht nicht sofort, sondern wird beim nächsten Bereitstellen des Hauptthreads als Arbeit am Hauptthread geplant.Ich würde vorschlagen, eine hinzuzufügen
Methode zu Ihrem
Fragment
und setzen Sie einen Haltepunkt darauf und sehen Sie, wann es relativ zu Ihrem Aufruf an aufgerufen wirdasd()
. Sie werden sehen, dass es nach der Methode aufgerufen wird, mit der Sieasd()
Exits aufrufen . DeronAttach
Aufruf ist derFragment
Ort, an dem der an seine Aktivität angehängt ist und ab diesem ZeitpunktgetActivity()
ungleich Null zurückgibt (nb gibt es auch einenonDetach()
Anruf).quelle
onCreateView
oderonActivityCreated
Methoden. Ich frage mich, warum asd () aufgerufen werden muss, wenn dies in der Posting-Frage der Fall ist.commitNow()
Das Beste, um dies zu beseitigen, ist, die Aktivitätsreferenz beizubehalten, wenn onAttach aufgerufen wird, und die Aktivitätsreferenz zu verwenden, wo immer dies erforderlich ist, z
quelle
onDestroy()
undonDetach()
weilonDestroy()
nicht garantiert wird, dass es aufgerufen wird.Activity
wenn wir es nicht aufhebenonDestroy()
?Dies geschah, wenn Sie einen
getActivity()
anderen Thread aufrufen , der beendet wurde, nachdem das Fragment entfernt wurde. Der typische Fall ist das AufrufengetActivity()
(z. B. für aToast
), wenn eine HTTP-Anforderung beendet wurde (inonResponse
z. B. z. B. in).Um dies zu vermeiden, können Sie einen Feldnamen definieren
mActivity
und stattdessen verwendengetActivity()
. Dieses Feld kann in der onAttach () -Methode von Fragment wie folgt initialisiert werden:In meinen Projekten definiere ich normalerweise eine Basisklasse für alle meine Fragmente mit dieser Funktion:
Viel Spaß beim Codieren,
quelle
Activity
von einem anderen Thread aus zuzugreifen . Sie können sowieso nichts damit anfangen, nicht einmal einen Toast zeigen. Sie sollten also entweder zuerst die Arbeit auf den Hauptthread übertragen oder Activity überhaupt nicht verwenden.Die anderen Antworten, die darauf hindeuten, einen Verweis auf die Aktivität in onAttach beizubehalten, deuten lediglich auf ein Bandaid für das eigentliche Problem hin. Wenn getActivity null zurückgibt, bedeutet dies, dass das Fragment nicht an die Aktivität angehängt ist. Am häufigsten geschieht dies, wenn die Aktivität aufgrund einer Rotation oder eines Abschlusses der Aktivität verschwunden ist, das Fragment jedoch noch eine Art Rückruf-Listener registriert hat. Wenn der Hörer angerufen wird, wenn Sie etwas mit der Aktivität tun müssen, die Aktivität jedoch nicht mehr vorhanden ist, können Sie nicht viel tun. In Ihrem Code sollten Sie nur überprüfen
getActivity() != null
und wenn es nicht da ist, dann tu nichts. Wenn Sie einen Verweis auf die Aktivität behalten, die nicht mehr vorhanden ist, verhindern Sie, dass die Aktivität durch Müll gesammelt wird. Alle UI-Dinge, die Sie möglicherweise versuchen, werden vom Benutzer nicht gesehen. Ich kann mir einige Situationen vorstellen, in denen Sie im Callback-Listener möglicherweise einen Kontext für etwas haben möchten, das nicht mit der Benutzeroberfläche zu tun hat. In diesen Fällen ist es wahrscheinlich sinnvoller, den Anwendungskontext abzurufen. Beachten Sie, dass der einzige Grund dafür, dass deronAttach
Trick kein großer Speicherverlust ist, darin besteht, dass er normalerweise nach der Ausführung des Rückruf-Listeners nicht mehr benötigt wird und zusammen mit dem Fragment, all seinen Ansichten und dem Aktivitätskontext Müll gesammelt werden kann. Wenn dusetRetainInstance(true)
Es besteht eine größere Wahrscheinlichkeit eines Speicherverlusts, da das Feld "Aktivität" ebenfalls beibehalten wird. Nach der Drehung kann dies jedoch die vorherige Aktivität sein, nicht die aktuelle.quelle
Seit Android API Level 23 ist onAttach (Aktivitätsaktivität) veraltet. Sie müssen onAttach (Kontextkontext) verwenden. http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)
Aktivität ist ein Kontext. Wenn Sie also einfach überprüfen können, ob es sich bei dem Kontext um eine Aktivität handelt, können Sie sie bei Bedarf umwandeln.
quelle
PJL ist richtig. Ich habe seinen Vorschlag verwendet und das habe ich getan:
definierte globale Variablen für Fragment:
private final Object attachingActivityLock = new Object();
private boolean syncVariable = false;
implementiert
3 . Ich habe meine Funktion, in der ich getActivity () aufrufen muss, im Thread abgeschlossen, da ich den Thread mit Schritt 4 blockieren würde, wenn er auf dem Hauptthread ausgeführt würde, und onAttach () niemals aufgerufen würde.
4. In meiner Funktion, in der ich getActivity () aufrufen muss, verwende ich dies (vor dem Aufruf von getActivity ()).
Wenn Sie einige UI-Updates haben, denken Sie daran, diese auf dem UI-Thread auszuführen. Ich muss ImgeView aktualisieren, damit ich Folgendes tun kann:
quelle
Die Reihenfolge, in der die Rückrufe nach commit () aufgerufen werden:
Ich musste einige Arbeiten ausführen, die einige Ansichten beinhalteten, daher funktionierte onAttach () für mich nicht. es stürzte ab. Also habe ich einen Teil meines Codes verschoben, der einige Parameter in einer Methode festlegte, die direkt nach commit () (1.) aufgerufen wurde, und dann den anderen Teil des Codes, der die Ansicht in onCreateView () (3.) verarbeitet hat.
quelle
Ich benutze OkHttp und habe mich gerade diesem Problem gestellt.
Für den ersten Teil war @thucnguyen auf dem richtigen Weg .
Einige HTTP-Aufrufe wurden auch nach Abschluss der Aktivität ausgeführt (da es eine Weile dauern kann, bis eine HTTP-Anforderung abgeschlossen ist). Ich habe dann durch das
HttpCallback
versucht, einige Fragmentfelder zu aktualisieren und habenull
beim Versuch eine Ausnahme bekommengetActivity()
.IMO besteht die Lösung darin , Rückrufe zu verhindern, wenn das Fragment nicht mehr lebt (und das nicht nur bei Okhttp).
Das Update: Prävention.
Wenn Sie sich den Fragmentlebenszyklus ansehen (weitere Informationen hier ), werden Sie feststellen, dass es
onAttach(Context context)
und gibtonDetach()
Methoden. Diese werden aufgerufen, nachdem das Fragment zu einer Aktivität gehört und kurz bevor es aufhört.Das bedeutet, dass wir diesen Rückruf verhindern können, indem wir ihn in der
onDetach
Methode steuern .quelle
Wo nennt man diese Funktion? Wenn Sie es im Konstruktor von aufrufen
Fragment
, wird es zurückgegebennull
.Rufen Sie einfach auf,
getActivity()
wenn die MethodeonCreateView()
ausgeführt wird.quelle
Gehen Sie wie folgt vor. Ich denke, es wird Ihnen hilfreich sein.
quelle
Diejenigen, die immer noch das Problem mit onAttach (Aktivitätsaktivität) haben, haben es einfach in Kontext geändert -
In den meisten Fällen reicht es aus, den Kontext zu speichern. Wenn Sie beispielsweise getResources () ausführen möchten, können Sie dies direkt aus dem Kontext heraus tun. Wenn Sie den Kontext noch in Ihre Aktivität integrieren müssen, tun Sie dies -
Wie von user1868713 vorgeschlagen.
quelle
Sie können onAttach verwenden oder wenn Sie onAttach nicht überall einsetzen möchten, können Sie eine Methode einfügen, die ApplicationContext für die Haupt-App-Klasse zurückgibt:
Danach können Sie es überall in Ihrem Projekt wie folgt wiederverwenden:
Bitte lassen Sie mich wissen, wenn dies bei Ihnen nicht funktioniert.
quelle
Eine weitere gute Lösung wäre die Verwendung von Android LiveData mit MVVM-Architektur. Sie würden ein LiveData-Objekt in Ihrem ViewModel definieren und es in Ihrem Fragment beobachten. Wenn der LiveData-Wert geändert wird, wird Ihr Beobachter (in diesem Fall das Fragment) nur benachrichtigt, wenn sich Ihr Fragment im aktiven Zustand befindet, sodass Sie garantiert sind würde Ihre Benutzeroberfläche funktionieren lassen und nur dann auf die Aktivität zugreifen, wenn sich Ihr Fragment im aktiven Zustand befindet. Dies ist ein Vorteil, der damit verbunden ist LiveData
Als diese Frage zum ersten Mal gestellt wurde, gab es natürlich keine LiveData. Ich lasse diese Antwort hier, weil es, wie ich sehe, immer noch dieses Problem gibt und es für jemanden hilfreich sein könnte.
quelle
Rufen Sie die Methode getActivity () in onActivityCreated () auf.
quelle