Ponieważ (mówisz) warto zadzwonić do super onCreate first: pomyśl o tym.
Kiedy chcę tworzyć, Moje super tworzy swoje zasoby> Tworzę swoje zasoby.
Odwrotnie: (rodzaj stosu)
Kiedy chcę zniszczyć, niszczę swoje zasoby> Mój super niszczy jego zasoby.
W tym sensie ma zastosowanie do dowolnej pary funkcji (onCreate / onDestroy, onResume / onPause, onStart / onStop). Oczywiście onCreate utworzy zasoby, a onDestroy je zwolni. Nawiasem mówiąc, ten sam dowód dotyczy innych par.
Rozważmy pobraną bibliotekę, która ma funkcję LocationActivity zawierającą funkcję getLocation (), która zapewnia lokalizację. Najprawdopodobniej to działanie będzie musiało zainicjować swoje rzeczy w onCreate (), co zmusi cię do wywołania najpierw super.onCreate. Już to robisz, bo czujesz, że to ma sens. Teraz w swoim onDestroy decydujesz, że chcesz zapisać lokalizację gdzieś w SharedPreferences. Jeśli najpierw wywołasz super.onDestroy, jest do pewnego stopnia możliwe, że getLocation zwróci wartość null po tym wywołaniu, ponieważ implementacja LocationActivity unieważnia wartość lokalizacji w onDestroy. Chodzi o to, że nie możesz tego winić, jeśli tak się stanie. Dlatego na koniec nazwałbyś super.onDestroy, gdy skończysz z własnym onDestroy. Mam nadzieję, że to trochę sensowne.
Jeśli powyższe ma sens, weź pod uwagę, że w dowolnym momencie prowadzimy działalność, która jest zgodna z powyższą koncepcją. Jeśli chcę rozszerzyć tę aktywność, prawdopodobnie będę czuć to samo i postępować zgodnie z tym samym porządkiem z powodu tego samego dokładnego argumentu.
Przez indukcję każda czynność powinna robić to samo. Oto dobra klasa abstrakcyjna dla zajęć, które muszą przestrzegać następujących zasad:
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);
}
}
Wreszcie, co się stanie, jeśli Twoja aktywność o nazwie AnudeepBullaActivity
rozszerzy BaseActivity, a później chcę utworzyć, SherifElKhatibActivity
która rozszerzy Twoją aktywność? W jakiej kolejności mam wywoływać super.do
funkcje? Ostatecznie jest to to samo.
Co do twojego pytania:
Myślę, że intencją Google jest powiedzenie nam: proszę dzwonić do super bez względu na to, gdzie. Jako ogólną praktykę nazwij to oczywiście na początku. Google ma oczywiście najzdolniejszych inżynierów i programistów, więc prawdopodobnie wykonali dobrą robotę izolując ich super wywołania i nie ingerując w rozmowy dzieci.
Trochę próbowałem i prawdopodobnie nie jest łatwo (ponieważ to Google staramy się udowodnić, że się mylimy), aby utworzyć działanie, które ulegnie awarii z powodu wywołania When is super.
Czemu?
Cokolwiek zrobione w tych funkcjach jest tak naprawdę prywatne dla klasy Activity i nigdy nie spowodowałoby konfliktu z twoją podklasą. Na przykład (onDestroy)
protected void onDestroy() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
mCalled = true;
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;
}
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();
}
if (mSearchManager != null) {
mSearchManager.stopSearch();
}
getApplication().dispatchActivityDestroyed(this);
}
mManagedCursors i mManagedDialogs oraz mSearchManager są polami prywatnymi. To, co się tutaj dzieje, nie będzie miało wpływu na żaden publiczny / chroniony interfejs API.
Jednak w interfejsie API 14 dodano dispatchActivityDestroyed w celu wysłania onActivityDestroyed do ActivityLifecycleCallbacks zarejestrowanego w aplikacji. Dlatego każdy kod, który zależałby od jakiejś logiki w Twoim ActivityLifecycleCallbacks, będzie miał inny wynik w zależności od tego, kiedy dzwonisz do super. Na przykład:
Utwórz klasę aplikacji, która zlicza liczbę aktualnie uruchomionych działań:
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) {}
}
Poniższe informacje mogą nie mieć sensu lub nie są dobrą praktyką, ale służą tylko do udowodnienia racji (można znaleźć bardziej realną sytuację). Utwórz MainActivity, które rzekomo przechodzi do działania GoodBye, gdy jest zakończone i kiedy jest to ostatnie działanie:
@Override
protected void onDestroy() {
super.onDestroy();
if(((SherifApplication) getApplication()).getCount() == 0) {
startActivity(new Intent(this, GoodBye.class));
}
}
Jeśli zadzwonisz do super.onDestroy na początku swojego onDestroy, zostanie uruchomiona aktywność GoodBye. Jeśli zadzwonisz do super.onDestroy pod koniec operacji onDestroy, działanie GoodBye nie zostanie uruchomione.
Oczywiście nie jest to optymalny przykład. To jednak pokazuje, że Google trochę tu popsuło. Żadna z pozostałych zmiennych nie wpłynęłaby na zachowanie aplikacji. Jednak dodanie tych komunikatów do onDestroy spowodowało, że super-klasa w jakiś sposób kolidowała z twoją podklasą.
Mówię, że zadzierali też z innego powodu. Nie tylko dotykali (przed api 14) tylko w super wywołaniach tego, co jest ostateczne i / lub prywatne, ale także nazywali różne funkcje wewnętrzne (prywatne), które w rzeczywistości wywoływały funkcje onPause….
Na przykład performStop
function to funkcja o nazwie, która z kolei wywołuje funkcję onStop:
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;
}
Zauważ, że gdzieś w tej funkcji wywołują one funkcję onStop działania. Dlatego mogliby równie dobrze umieścić cały kod (zawarty w super.onStop) przed lub po wywołaniu onStop, a następnie po prostu powiadomić podklasy o onStop, używając pustych super funkcji onStop i nawet bez dodawania wyjątku SuperNotCalledException lub sprawdzania tego wywołania.
W tym celu, gdyby wywołali tę wysyłkę do ActivityLifeCycle w performDestroy, zamiast wywoływać ją na końcu super.onDestroy, zachowanie naszej aktywności byłoby takie samo niezależnie od tego, kiedy wywołaliśmy super.
W każdym razie jest to pierwsza rzecz, którą robią (trochę źle) i jest to tylko w API 14.