(あなたが言うには) 最初に super onCreate を呼び出すのは理にかなっています: 考えてみてください。
私が作成したいとき、私のスーパーはそのリソースを作成します > 私は自分のリソースを作成します。
逆に: (一種のスタック)
私が破壊したいとき、私は自分のリソースを破壊します > 私のスーパーは彼のリソースを破壊します.
この意味で、これは任意の関数 (onCreate/onDestroy、onResume/onPause、onStart/onStop) に適用されます。当然、onCreate はリソースを作成し、onDestroy はこれらのリソースを解放します。ちなみに、他のカップルについても同様の証明が成り立ちます。
場所を提供する getLocation() 関数を含む LocationActivity を持つ、ダウンロードしたライブラリを考えてみましょう。ほとんどの場合、このアクティビティは onCreate() でその内容を初期化する必要があるため、最初に super.onCreate を呼び出す必要があります。あなたはそれが理にかなっていると感じているので、すでにそれを行っています。ここで、onDestroy で、場所を SharedPreferences のどこかに保存することを決定します。最初に super.onDestroy を呼び出すと、この呼び出しの後に getLocation が null 値を返す可能性がある程度あります。これは、LocationActivity の実装が onDestroy の場所の値を無効にするためです。これが起こっても、あなたはそれを責めないだろうという考えです。したがって、独自の onDestroy を使用した後、最後に super.onDestroy を呼び出します。これが少し理にかなっていることを願っています。
上記が理にかなっている場合は、いつでも上記の概念に従う活動があると考えてください。もし私がこの活動を拡張したいのなら、私はおそらく同じように感じ、まったく同じ議論のために同じ順序に従うでしょう.
誘導により、どのアクティビティも同じことを行う必要があります。以下は、これらの規則に従うことを余儀なくされたアクティビティに適した抽象クラスです。
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);
}
}
最後に、呼び出されたアクティビティAnudeepBullaActivity
が BaseActivity を拡張し、後でアクティビティを拡張するものを作成したい場合はどうすればよいSherifElKhatibActivity
でしょうか? どのような順序でsuper.do
関数を呼び出す必要がありますか? それは結局同じことです。
あなたの質問について:
Google の意図は、私たちに次のように伝えることだと思います。どこにいてもスーパーに電話してください。もちろん、一般的な慣行として、最初に呼び出します。もちろん、Google には最も優れたエンジニアと開発者がいます。そのため、スーパー コールを分離し、子コールに干渉しないようにうまく機能したと考えられます。
少し試してみましたが、スーパーが呼び出されたときに簡単にクラッシュするアクティビティを作成するのはおそらく簡単ではありません (Google が間違っていることを証明しようとしているため)。
なんで?
これらの関数で行われることはすべて、Activity クラスにとって本当にプライベートであり、サブクラスと競合することはありません。たとえば (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 と mManagedDialogs と mSearchManager はすべてプライベート フィールドです。また、公開/保護された API は、ここで行われることの影響を受けません。
ただし、API 14 では、アプリケーションに登録されている ActivityLifecycleCallbacks に onActivityDestroyed をディスパッチするために、dispatchActivityDestroyed が追加されました。したがって、ActivityLifecycleCallbacks の何らかのロジックに依存するコードは、いつスーパーを呼び出すかによって結果が異なります。例えば:
現在実行中のアクティビティの数をカウントするアプリケーション クラスを作成します。
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) {}
}
以下は意味をなさないか、良い習慣ではないかもしれませんが、要点を証明するためのものです (より現実的な状況が見つかるかもしれません)。GoodBye アクティビティが終了し、最後のアクティビティになると想定される MainActivity を作成します。
@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));
}
}
onDestroy の最初に super.onDestroy を呼び出すと、GoodBye アクティビティが開始されます。onDestroy の最後に super.onDestroy を呼び出すと、GoodBye アクティビティは開始されません。
もちろん、繰り返しますが、これは最適な例ではありません。ただし、これは、Google がここで少し失敗したことを示しています。他の変数はアプリの動作に影響しません。ただし、これらのディスパッチを onDestroy に追加すると、スーパーが何らかの形でサブクラスに干渉しました。
彼らは別の理由でも台無しにしたと言います。彼らは(API 14より前に)スーパーコールでfinalおよび/またはprivateに触れるだけでなく、実際にonPause ...関数をディスパッチするさまざまな内部関数(private)も呼び出しました。
たとえば、performStop
function は呼び出された関数であり、次に 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;
}
この関数のどこかでアクティビティの onStop を呼び出していることに注意してください。したがって、すべてのコード (super.onStop に含まれる) を onStop の呼び出しの前または後に配置し、空の onStop スーパー関数を使用して onStop についてサブクラスに通知するだけで、SuperNotCalledException を追加したり、これが呼び出されたことを確認したりすることさえありません。
このため、super.onDestroy の最後で呼び出すのではなく、performDestroy で ActivityLifeCycle へのこのディスパッチを呼び出した場合、スーパーをいつ呼び出したかに関係なく、アクティビティの動作は同じになります。
とにかく、これは彼らが最初に行うことであり (少し間違っています)、API 14 のみです。