Já que (você diz) faz sentido chamar super onCreate primeiro: Pense nisso.
Quando eu quero criar, Meu super cria seus recursos> Eu crio meus recursos.
Inversamente: (uma espécie de pilha)
Quando eu quero destruir, eu destruo meus recursos> Meu super destrói seus recursos.
Nesse sentido, ele se aplica a qualquer par de funções (onCreate / onDestroy, onResume / onPause, onStart / onStop). Naturalmente, onCreate criará recursos e onDestroy irá liberar esses recursos. Aliás, a mesma prova vale para os outros casais.
Vamos considerar uma biblioteca que você baixou que tem um LocationActivity que contém uma função getLocation () que fornece o local. Muito provavelmente, esta atividade precisará inicializar seu material no onCreate (), o que o forçará a chamar o super.onCreate primeiro. Você já faz isso porque sente que faz sentido. Agora, em seu onDestroy, você decide que deseja salvar o local em algum lugar em SharedPreferences. Se você chamar super.onDestroy primeiro, é até certo ponto possível que getLocation retorne um valor nulo após essa chamada porque a implementação de LocationActivity anula o valor de local em onDestroy. A ideia é que você não culparia se isso acontecesse. Portanto, você chamaria super.onDestroy no final, depois de concluir o seu próprio onDestroy. Espero que isso faça algum sentido.
Se o exposto acima fizer sentido, considere que a qualquer momento temos uma atividade que segue o conceito acima. Se eu quiser estender esta atividade, provavelmente vou me sentir da mesma maneira e seguir a mesma ordem por causa do mesmo argumento exato.
Por indução, qualquer atividade deve fazer a mesma coisa. Aqui está uma boa classe abstrata para uma atividade forçada a seguir estas regras:
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);
}
}
Finalmente, e se sua atividade chamada AnudeepBullaActivity
estende BaseActivity e, posteriormente, eu quero criar SherifElKhatibActivity
que estende sua atividade? Em que ordem devo chamar as super.do
funções? Em última análise, é a mesma coisa.
Quanto à sua pergunta:
Acho que a intenção do Google é nos dizer: ligue para o supervisor, não importa onde. Como uma prática geral, é claro, chame-o no início. O Google, é claro, tem os engenheiros e desenvolvedores mais brilhantes, então eles provavelmente fizeram um bom trabalho ao isolar suas super chamadas e não interferir nas chamadas secundárias.
Tentei um pouco e provavelmente não é fácil (já que é o Google que estamos tentando provar que estamos errados) criar uma atividade que travaria simplesmente por causa de When está sendo super chamado.
Por quê?
Qualquer coisa feita nessas funções é realmente privada para a classe Activity e nunca causaria qualquer conflito com sua subclasse. Por exemplo (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 e mManagedDialogs e mSearchManager são todos campos privados. E nenhuma API pública / protegida será afetada pelo que é feito aqui.
No entanto, na API 14, dispatchActivityDestroyed foi adicionado para despachar um onActivityDestroyed para ActivityLifecycleCallbacks registrados em seu aplicativo. Portanto, qualquer código que dependa de alguma lógica em ActivityLifecycleCallbacks terá um resultado diferente com base em quando você está chamando o super. Por exemplo:
Crie uma classe de aplicativo que conte o número de atividades em execução no momento:
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) {}
}
O seguinte pode não fazer sentido ou não ser uma boa prática, mas é apenas para provar um ponto (pode-se encontrar uma situação mais real). Crie a MainActivity que supostamente vai para a atividade GoodBye quando for concluída e quando for a última atividade:
@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));
}
}
Se você chamar super.onDestroy no início de seu onDestroy, a atividade GoodBye será iniciada. Se você chamar super.onDestroy no final de seu onDestroy, a atividade GoodBye não será iniciada.
Claro, novamente, este não é o exemplo ideal. No entanto, isso mostra que o Google bagunçou um pouco aqui. Qualquer uma das outras variáveis não teria afetado o comportamento do seu aplicativo. No entanto, adicionar esses despachos ao onDestroy fazia com que o super interferisse de alguma forma em sua subclasse.
Eu digo que eles bagunçaram por um motivo diferente também. Eles não apenas (antes da api 14) apenas tocavam nas super chamadas o que é final e / ou privado, mas também chamavam diferentes funções internas (privadas) que realmente despachavam as funções onPause ....
Por exemplo, performStop
function é a função chamada que, por sua vez, chama a função 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;
}
Observe que eles chamam onStop da atividade em algum lugar desta função. Portanto, eles também podem ter colocado todo o código (incluído em super.onStop) antes ou depois da chamada para onStop e, em seguida, apenas notificar as subclasses sobre onStop usando superfunções onStop vazias e sem nem mesmo adicionar a SuperNotCalledException ou verificar se ela foi chamada.
Para isso, se eles chamaram esse despacho para ActivityLifeCycle em performDestroy em vez de chamá-lo no final de super.onDestroy, o comportamento de nossa atividade teria sido o mesmo, independentemente de quando chamamos o super.
De qualquer forma esta é a primeira coisa que eles fazem (um pouco errado) e é apenas na API 14.