Da (Sie sagen) es sinnvoll ist, zuerst super onCreate aufzurufen: Denken Sie darüber nach.
Wenn ich erstellen möchte, erstellt My Super seine Ressourcen> Ich erstelle meine Ressourcen.
Umgekehrt: (eine Art Stapel)
Wenn ich zerstören will, zerstöre ich meine Ressourcen> Mein Super zerstört seine Ressourcen.
In diesem Sinne gilt es für einige Funktionen (onCreate / onDestroy, onResume / onPause, onStart / onStop). Natürlich erstellt onCreate Ressourcen und onDestroy gibt diese Ressourcen frei. Der gleiche Beweis gilt übrigens auch für die anderen Paare.
Betrachten wir eine von Ihnen heruntergeladene Bibliothek mit einer LocationActivity, die eine Funktion getLocation () enthält, die den Speicherort bereitstellt. Höchstwahrscheinlich muss diese Aktivität ihre Inhalte in onCreate () initialisieren, wodurch Sie gezwungen werden, zuerst die Datei super.onCreate aufzurufen. Das machst du schon, weil du denkst, dass es Sinn macht. Jetzt entscheiden Sie in Ihrem onDestroy, dass Sie den Speicherort irgendwo in den SharedPreferences speichern möchten. Wenn Sie zuerst super.onDestroy aufrufen, ist es bis zu einem gewissen Grad möglich, dass getLocation nach diesem Aufruf einen Nullwert zurückgibt, da die Implementierung von LocationActivity den Standortwert in onDestroy aufhebt. Die Idee ist, dass Sie es nicht beschuldigen würden, wenn dies passiert. Daher würden Sie am Ende super.onDestroy aufrufen, nachdem Sie mit Ihrem eigenen onDestroy fertig sind. Ich hoffe das macht ein bisschen Sinn.
Wenn das oben Gesagte Sinn macht, denken Sie daran, dass wir zu jedem Zeitpunkt eine Aktivität haben, die dem obigen Konzept entspricht. Wenn ich diese Aktivität erweitern möchte, werde ich wahrscheinlich genauso denken und aufgrund des gleichen genauen Arguments der gleichen Reihenfolge folgen.
Durch Induktion sollte jede Aktivität dasselbe tun. Hier ist eine gute abstrakte Klasse für eine Aktivität, die gezwungen ist, diese Regeln zu befolgen:
package mobi.sherif.base;
import android.app.Activity;
import android.os.Bundle;
public abstract class BaseActivity extends Activity {
protected abstract void doCreate(Bundle savedInstanceState);
protected abstract void doDestroy();
protected abstract void doResume();
protected abstract void doPause();
protected abstract void doStart();
protected abstract void doStop();
protected abstract void doSaveInstanceState(Bundle outState);
@Override
protected final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
doCreate(savedInstanceState);
}
@Override
protected final void onDestroy() {
doDestroy();
super.onDestroy();
}
@Override
protected final void onResume() {
super.onResume();
doResume();
}
@Override
protected final void onPause() {
doPause();
super.onPause();
}
@Override
protected final void onStop() {
doStop();
super.onStop();
}
@Override
protected final void onStart() {
super.onStart();
doStart();
}
@Override
protected final void onSaveInstanceState(Bundle outState) {
doSaveInstanceState(outState);
super.onSaveInstanceState(outState);
}
}
Was ist, wenn Ihre Aktivität AnudeepBullaActivity
BaseActivity erweitert und ich später SherifElKhatibActivity
eine Aktivität erstellen möchte, die Ihre Aktivität erweitert? In welcher Reihenfolge soll ich die super.do
Funktionen aufrufen ? Es ist letztendlich das Gleiche.
Wie für Ihre Frage:
Ich denke, Google will uns sagen: Bitte rufen Sie den Super an, egal wo. Als allgemeine Praxis nennen Sie es natürlich am Anfang. Google hat natürlich die klügsten Ingenieure und Entwickler, daher haben sie wahrscheinlich gute Arbeit geleistet, um ihre Superanrufe zu isolieren und die untergeordneten Anrufe nicht zu stören.
Ich habe ein bisschen versucht und es ist wahrscheinlich nicht einfach (da es sich um Google handelt, versuchen wir, das Gegenteil zu beweisen), eine Aktivität zu erstellen, die einfach abstürzt, weil Wann super aufgerufen wird.
Warum?
Alles, was in diesen Funktionen ausgeführt wird, ist für die Aktivitätsklasse wirklich privat und würde niemals zu Konflikten mit Ihrer Unterklasse führen. Zum Beispiel (onDestroy)
protected void onDestroy() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
mCalled = true;
// dismiss any dialogs we are managing.
if (mManagedDialogs != null) {
final int numDialogs = mManagedDialogs.size();
for (int i = 0; i < numDialogs; i++) {
final ManagedDialog md = mManagedDialogs.valueAt(i);
if (md.mDialog.isShowing()) {
md.mDialog.dismiss();
}
}
mManagedDialogs = null;
}
// close any cursors we are managing.
synchronized (mManagedCursors) {
int numCursors = mManagedCursors.size();
for (int i = 0; i < numCursors; i++) {
ManagedCursor c = mManagedCursors.get(i);
if (c != null) {
c.mCursor.close();
}
}
mManagedCursors.clear();
}
// Close any open search dialog
if (mSearchManager != null) {
mSearchManager.stopSearch();
}
getApplication().dispatchActivityDestroyed(this);
}
mManagedCursors und mManagedDialogs sowie mSearchManager sind private Felder. Und keine der öffentlichen / geschützten APIs wird von dem, was hier getan wird, betroffen sein.
In API 14 wurde jedoch dispatchActivityDestroyed hinzugefügt, um onActivityDestroyed an die in Ihrer Anwendung registrierten ActivityLifecycleCallbacks zu senden. Daher hat jeder Code, der von einer Logik in Ihren ActivityLifecycleCallbacks abhängt, ein anderes Ergebnis, je nachdem, wann Sie den Super aufrufen. Beispielsweise:
Erstellen Sie eine Anwendungsklasse, die die Anzahl der aktuell ausgeführten Aktivitäten zählt:
package mobi.shush;
import android.app.Activity;
import android.app.Application;
import android.app.Application.ActivityLifecycleCallbacks;
import android.os.Bundle;
public class SherifApplication extends Application implements ActivityLifecycleCallbacks {
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
public int getCount() {
return count;
}
int count = 0;
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
count++;
}
@Override
public void onActivityDestroyed(Activity activity) {
count--;
}
@Override
public void onActivityPaused(Activity activity) {}
@Override
public void onActivityResumed(Activity activity) {}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
@Override
public void onActivityStarted(Activity activity) {}
@Override
public void onActivityStopped(Activity activity) {}
}
Das Folgende mag keinen Sinn ergeben oder ist keine gute Praxis, aber es dient nur dazu, einen Punkt zu beweisen (man könnte eine realere Situation finden). Erstellen Sie die MainActivity, die angeblich zur GoodBye-Aktivität geht, wenn sie abgeschlossen ist und wenn es die letzte Aktivität ist:
@Override
protected void onDestroy() {
super.onDestroy();
if(((SherifApplication) getApplication()).getCount() == 0) {
//i want to go to a certain activity when there are no other activities
startActivity(new Intent(this, GoodBye.class));
}
}
Wenn Sie zu Beginn Ihres onDestroy super.onDestroy aufrufen, wird die GoodBye-Aktivität gestartet. Wenn Sie am Ende Ihres onDestroy super.onDestroy aufrufen, wird die GoodBye-Aktivität nicht gestartet.
Auch dies ist natürlich nicht das optimale Beispiel. Dies zeigt jedoch, dass Google hier etwas durcheinander gebracht hat. Alle anderen Variablen hätten das Verhalten Ihrer App nicht beeinflusst. Das Hinzufügen dieses Versands zu onDestroy führte jedoch dazu, dass der Super Ihre Unterklasse irgendwie störte.
Ich sage, sie haben auch aus einem anderen Grund durcheinander gebracht. Sie haben nicht nur (vor API 14) in den Superaufrufen nur das berührt, was endgültig und / oder privat ist, sondern sie haben auch verschiedene interne Funktionen (privat) aufgerufen, die dann wirklich die onPause ... -Funktionen ausgelöst haben.
Beispielsweise ist performStop
function die aufgerufene Funktion, die wiederum die onStop-Funktion aufruft:
final void performStop() {
if (mLoadersStarted) {
mLoadersStarted = false;
if (mLoaderManager != null) {
if (!mChangingConfigurations) {
mLoaderManager.doStop();
} else {
mLoaderManager.doRetain();
}
}
}
if (!mStopped) {
if (mWindow != null) {
mWindow.closeAllPanels();
}
if (mToken != null && mParent == null) {
WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
}
mFragments.dispatchStop();
mCalled = false;
mInstrumentation.callActivityOnStop(this);
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onStop()");
}
synchronized (mManagedCursors) {
final int N = mManagedCursors.size();
for (int i=0; i<N; i++) {
ManagedCursor mc = mManagedCursors.get(i);
if (!mc.mReleased) {
mc.mCursor.deactivate();
mc.mReleased = true;
}
}
}
mStopped = true;
}
mResumed = false;
}
Beachten Sie, dass sie irgendwo in dieser Funktion den onStop der Aktivität aufrufen. Daher haben sie möglicherweise auch den gesamten Code (in super.onStop enthalten) vor oder nach dem Aufruf von onStop eingefügt und dann Unterklassen über leere onStop-Superfunktionen benachrichtigt, ohne die SuperNotCalledException hinzuzufügen oder nach diesem Aufruf zu suchen.
Wenn sie diesen Versand an den ActivityLifeCycle im performDestroy aufgerufen hätten, anstatt ihn am Ende von super.onDestroy aufzurufen, wäre das Verhalten unserer Aktivität unabhängig davon, wann wir den super aufgerufen haben, dasselbe gewesen.
Auf jeden Fall ist dies das erste, was sie tun (ein bisschen falsch) und es ist nur in API 14.