onPause、onStop、onDestroyメソッドでスーパークラスメソッドを呼び出す正しい順序は何ですか?なぜ?


89

私はAndroidデベロッパーサイトを閲覧して、アクティビティライフサイクルを更新していました。各コード例では、スーパークラスメソッドの横に「常に最初にスーパークラスメソッドを呼び出す」というコメントがあります。

これは、作成の半サイクル(onCreate、onStart、onResume)では理にかなっていますが、破壊の半サイクルでの正しい手順について少し混乱しています:onPause、onStop、onDestroy。

インスタンス固有のリソースを破棄する前に、インスタンス固有のリソースを破棄する前に、インスタンス固有のリソースが依存する可能性のあるスーパークラスのリソースを破棄するのは理にかなっていますが、コメントはそうではありません。何が欠けていますか?

編集:質問の意図について人々が混乱しているように見えるので、私が知りたいのは次のうちどれが正しいのですか?なぜ ?

1.Googleが提案する

    @Override
    protected void onStop() {
      super.onStop();  // Always call the superclass method first

      //my implementation here
    }

2.その他の方法

    @Override
    protected void onStop() {
       //my implementation here

       super.onStop();  
    }

1
シャットダウン方法について私はキャンプ2にいます。私はスタートアップ方法のキャンプ1にいます。
danny117 2013

1
それがポイントです。シャットダウンメソッドにメソッド1を使用することが理にかなっていることを理解できませんでした。
Anudeep Bulla 2013

回答:


107

インスタンス固有のリソースが依存する可能性のあるスーパークラスリソースを破棄する前に、まずインスタンス固有のリソースを破棄することは理にかなっており、その逆ではありません。しかし、コメントはそうでないことを示唆しています。何が欠けていますか?

私の意見では、単一のものではありません。

マーク(SOの別名CommonsWare)からのこの回答は、問題に光を当てています。リンク-スーパークラスメソッドの呼び出しを最初のステートメントにする必要がありますか?。しかし、それから彼の答えに残っている次のコメントを見ることができます:

しかし、公式ドキュメントがonPause()で「常に最初にスーパークラスメソッドを呼び出す」と言っているのはなぜですか

振り出しに戻って。さて、これを別の角度から見てみましょう。Java言語仕様で、への呼び出しを行うsuper.overridenMethod()必要がある順序を指定していない(または呼び出しを行う必要がある場合)ことわかってます。

クラスActivityの場合、super.overridenMethod()呼び出しが必要であり、強制されます。

if (!mCalled) {
    throw new SuperNotCalledException(
        "Activity " + mComponent.toShortString() +
            " did not call through to super.onStop()");
}

mCalledでtrueに設定されていますActivity.onStop()

さて、議論の余地があるのは注文だけです。

I also know that both work

承知しました。Activity.onPause()のメソッド本体を見てください。

protected void onPause() {
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);

    // This is to invoke 
    // Application.ActivityLifecyleCallbacks.onActivityPaused(Activity)
    getApplication().dispatchActivityPaused(this);

    // The flag to enforce calling of this method
    mCalled = true;
}

どちらの方法で呼び出しを挟む super.onPause()も、大丈夫です。Activity.onStop()にも同様のメソッド本体があります。しかし、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);
}

ここで、注文は 、アクティビティの設定方法、および呼び出しsuper.onDestroy()が後続のコードに干渉するかどうかによって問題になる可能性あります。

最後の言葉として、声明Always call the superclass method firstはそれを裏付ける証拠があまりないようです。さらに悪いことに(ステートメントに関して)、次のコードが以下から取得されていますandroid.app.ListActivity

public class ListActivity extends Activity {

    ....

    @Override
    protected void onDestroy() {
        mHandler.removeCallbacks(mRequestFocus);
        super.onDestroy();
    }
    ....    
}

そして、Android SDKに含まれているLunarLanderサンプルアプリケーションから:

public class LunarLander extends Activity {

    ....

    @Override
    protected void onPause() {
        mLunarView.getThread().pause(); // pause game when Activity pauses
        super.onPause();
    }
    ....
}

まとめと価値ある言及:

ユーザーPhilip Sheard:がsuper.onPause()アクティビティの使用を開始した場合にへの呼び出しを遅らせる必要があるシナリオを提供しますstartActivityForResult(Intent)afterを使用して結果を設定するsetResult(...) super.onPause()をは機能しません。彼は後で彼の答えへのコメントでこれを明らかにします。

ユーザーSherif elKhatib:スーパークラスが最初にそのリソースを初期化し、最後にそのリソースを破棄させることがロジックから続く理由を説明します。

場所を提供するgetLocation()関数を含むLocationActivityを含むダウンロードしたライブラリを考えてみましょう。ほとんどの場合、このアクティビティは、onCreate()でその内容を初期化する必要があるため、最初にsuper.onCreateを呼び出す必要があります。あなたはそれが理にかなっていると感じるのであなたはすでにそれをしています。次に、onDestroyで、LocationをSharedPreferencesのどこかに保存することを決定します。最初にsuper.onDestroyを呼び出した場合、LocationActivityの実装がonDestroyの位置の値を無効にするため、この呼び出しの後にgetLocationがnull値を返す可能性はある程度あります。これが起こってもあなたはそれを責めないだろうという考えです。したがって、独自のonDestroyが完了したら、最後にsuper.onDestroyを呼び出します。

彼は続けて指摘します:子クラスが親クラスから(リソースの依存性の観点から)適切に分離されてsuper.X()いる場合、呼び出しは順序の仕様に準拠する必要はありません。

配置シナリオを読み取るために、このページに彼の答えを参照してくださいsuper.onDestroy()コールがないプログラムロジックに影響を与えます。

マークの答えから

コンポーネントの作成の一部であるオーバーライドするメソッド(onCreate()、onStart()、onResume()など)。最初のステートメントとしてスーパークラスにチェーンする必要があります。これにより、Androidがその前に作業を実行できるようになります。その仕事が行われたことに依存する何かをしようとする。

コンポーネントの破棄の一部であるオーバーライドするメソッド(onPause()、onStop()、onDestroy()など)は、最初に作業を行い、最後にスーパークラスにチェーンする必要があります。そうすることで、Androidが作業に依存する何かをクリーンアップする場合に備えて、最初に作業を完了します。

void以外のものを返すメソッド(onCreateOptionsMenu()など)では、特定の戻り値を強制する必要がある何かを具体的に実行していないと想定して、returnステートメントでスーパークラスにチェーンする場合があります。

それ以外のすべて(onActivityResult()など)は、全体としてあなた次第です。私は最初にスーパークラスにチェーンする傾向がありますが、問題が発生していない限り、後でチェーンしても問題ありません。

このスレッドからのボブカーンズ

それは良いパターンです((Markが上で提案したパターン)]が、いくつかの例外を見つけました。たとえば 、PreferenceActivityに適用したいテーマは、スーパークラスのonCreate()の前に配置しない限り有効になりません。

ユーザーSteve Benettもこれに注目しています。

スーパーコールのタイミングが必要な状況は1つだけ知っています。onCreateでテーマやディスプレイなどの標準的な動作を変更する場合は、superを呼び出して効果を確認する前に変更する必要があります。それ以外の場合、私の知る限り、それを呼び出すときに違いはありません。

ユーザーSunil Mishraは、Activityクラスのメソッドを呼び出すときに、順序(ほとんどの場合)が役割を果たさないことを確認します。彼はまた、スーパークラスのメソッドを最初に呼び出すことがベストプラクティスと見なされているも述べてます。しかし、これを裏付けることはできませんでした。

ユーザーLOG_TAG:スーパークラスコンストラクターの呼び出しを他のすべての前に行う必要がある理由を説明します。私の意見では、この説明は尋ねられる質問には追加されません。

エンドノート:信頼するが、検証する。このページのほとんどの回答は、このアプローチに従って、ステートメントAlways call the superclass method firstに論理的な裏付けがあるかどうかを確認します。結局のところ、そうではありません。少なくとも、Activityクラスの場合はそうではありません。一般に、スーパークラスのソースコードを読んで、スーパーのメソッドへの呼び出しの順序付けが必要かどうかを判断する必要があります。


2
ワオ。ポインタをありがとう。これと@Sherifの回答の両方が重要なコンテキストを提供します。どちらかがこのページの回答を要約できる場合は、承認済みとしてマークします。このページの1.Answersを親切に含めてください。2. @フィリップのこのページでの答え3. @ CommonsWareのこのページでの答え4. このディスカッション はするつもりですが、あなたのすばらしい答えのクレジットは欲しくありません。乾杯&感謝
Anudeep Bulla 2013

こんにちは。@Sherifが望まないように見て、要約してください。
Anudeep Bulla 2013

@AnudeepBullaこんにちはAnudeep、明日まで私をください。私の回答に関連資料を追加し、ここにコメントを残します。
Vikram 2013

@AnudeepBulla上記の要約を追加しました。何かを見逃した場合はお知らせください。
Vikram

@VikramはTL; DRです。その呼び出しonDestroyonStopラストは安全なデフォルトでありonPause、いくつかのケースでは物事がよりトリッキーになる可能性がありますか?最初に追加してもらえますか?自分で回答を編集したくなりましたが、この要約が正しいかどうかはわかりません。
Blaisorblade

12

(あなたが言う)最初にsuper onCreateを呼び出すのは理にかなっているので、考えてみてください。

作成したいときは、スーパーがリソースを作成します>リソースを作成します。

逆に:(スタックの一種)

破壊したいときは、リソースを破壊します>スーパーは彼のリソースを破壊します。


この意味で、これは任意の2つの関数(onCreate / onDestroy、onResume / onPause、onStart / onStop)に適用されます。当然、onCreateはリソースを作成し、onDestroyはこれらのリソースを解放します。ちなみに、同じ証明が他のカップルにも当てはまります。

ロケーションを提供するgetLocation()関数を含むLocationActivityを含むダウンロードしたライブラリを考えてみましょう。ほとんどの場合、このアクティビティは、onCreate()でその内容を初期化する必要があるため、最初にsuper.onCreateを呼び出す必要があります。あなたはそれが理にかなっていると感じるのであなたはすでにそれをしています 次に、onDestroyで、LocationをSharedPreferencesのどこかに保存することを決定します。最初にsuper.onDestroyを呼び出す場合、LocationActivityの実装がonDestroyの場所の値を無効にするため、この呼び出しの後にgetLocationがnull値を返す可能性はある程度あります。これが起こってもあなたはそれを責めないだろうという考えです。したがって、独自の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には優秀なエンジニアと開発者がいるので、彼らはおそらく、スーパーコールを分離し、子のコールに干渉しないようにうまく機能しています。

私は少し試しましたが、Whenがsuperが呼び出されているために単純にクラッシュするアクティビティを作成することはおそらく簡単ではありません(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より前の)スーパーコールで最終および/またはプライベートなものに触れただけでなく、実際にonPause ...関数をディスパッチするさまざまな内部関数(プライベート)も呼び出しました。

たとえば、performStopfunctionは呼び出された関数であり、次に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を呼び出していることに注意してください。したがって、onStopの呼び出しの前または後にすべてのコード(super.onStopに含まれている)を配置して、空のonStopスーパー関数を使用し、SuperNotCalledExceptionを追加したり、呼び出されたことを確認したりせずに、onStopについてサブクラスに通知するだけの場合もあります。

このため、super.onDestroyの最後に呼び出すのではなく、performDestroyでこのディスパッチをActivityLifeCycleに呼び出した場合、スーパーを呼び出したタイミングに関係なく、アクティビティの動作は同じになります。

とにかく、これは彼らが最初に行うこと(少し間違っています)であり、API 14でのみ発生します。


なぜsuper.onDestroy()を呼び出すことが最後に意味をなすのかという疑問はかつてありませんでした。ライブラリの例が大好きです。まさに伝えたかったこと。スタックの場合とまったく同じように、スーパーメソッドを最後の破壊サイクルの最後に呼び出すことに同意することはできません。データの偶発的な損失を防ぐためです。問題は、上記の前提を前提として、Googleが最初にスーパーメソッドを呼び出すことを主張する理由です。たぶん私もあなたも一見、まったく違うやり方でアプローチしているのではないかと思ったので、質問しました。乾杯
Anudeep Bulla 2013

ああ、グーグルの提案やその他の方法は見なかった:p!聞いてください。最初にonDestroyを呼び出すとクラッシュするアクティビティを作成してみます。あなたもそれを試す必要があります。乾杯
シェリフエルハティブ2013

@AnudeepBullaあなたは私の編集をチェックできます。そして、あなたは試してやめることができます。super.onおそらくあなたの活動をクラッシュさせることは決してないでしょう。
Sherif elKhatib 2013

ワオ。ポインタをありがとう。これと@Userの回答の両方が重要なコンテキストを提供します。どちらかがこのページの回答を要約できる場合は、承認済みとしてマークします。このページの1.Answersを親切に含めてください。2. @フィリップのこのページでの答え3. @ CommonsWareのこのページでの答え4. このディスカッション はするつもりですが、あなたのすばらしい答えのクレジットは欲しくありません。乾杯&感謝
Anudeep Bulla 2013

@AnudeepBullaどういたしまして。最終的な書き込みを誰が投稿するかをどのように決定するかはわかりません。
ビクラム2013

1

ここでは、Javaの観点から、この混乱に対するいくつかの解決策を示します。

this()とsuper()をコンストラクタの最初のステートメントにする必要があるのはなぜですか?

親クラスのコンストラクターは、サブクラスのコンストラクターの前に呼び出す必要があります。これにより、コンストラクターで親クラスのメソッドを呼び出す場合、親クラスは既に正しく設定されています。

あなたがやろうとしていること、スーパーコンストラクターに引数を渡すことは完全に合法です、あなたがしているようにそれらの引数をインラインで構築するか、それらをコンストラクターに渡してそしてそれらをスーパーに渡すだけです:

public MySubClassB extends MyClass {
        public MySubClassB(Object[] myArray) {
                super(myArray);
        }
}

コンパイラがこれを強制しなかった場合、これを行うことができます:

public MySubClassB extends MyClass {
        public MySubClassB(Object[] myArray) {
                someMethodOnSuper(); //ERROR super not yet constructed
                super(myArray);
        }
}

これは、実際には、サブクラスをpreclassの前に非公式化する必要があることを示しています。一方、Java要件は、スーパーコンストラクターの引数を特化することにより、クラスを特化することから私たちを「守ります」

親クラスにデフォルトのコンストラクターがある場合、コンパイラーによって自動的にsuperの呼び出しが挿入されます。JavaのすべてのクラスはObjectを継承するため、オブジェクトコンストラクターをなんらかの方法で呼び出し、最初に実行する必要があります。コンパイラーによるsuper()の自動挿入により、これが可能になります。スーパーが最初に表示されるように強制すると、コンストラクター本体が正しい順序で実行されるように強制されます。オブジェクト->親->子-> ChildOfChild-> SoOnSoForth

(1)superが最初のステートメントであることを確認するだけでは、その問題を防ぐには不十分です。たとえば、「super(someMethodInSuper());」と置くことができます。あなたのコンストラクタで。これは、superが最初のステートメントであっても、作成される前にスーパークラスのメソッドにアクセスしようとします。

(2)コンパイラは、それ自体でこの問題を防ぐのに十分な別のチェックを実装しているようです。メッセージは「スーパータイプコンストラクターが呼び出される前にxxxを参照できません」です。したがって、superが最初のステートメントであることを確認する必要はありません。

こちらをご覧くださいhttp://valjok.blogspot.in/2012/09/super-constructor-must-be-first.html


あなたが何を出しているのか完全に理解しています。最初にスーパークラスコンストラクターを呼び出します。子が必要とするリソースを初期化する場合があります。デストラクタは最後に、おそらくローカルリソースのすべての親を消去して、それらを無意味にする必要はありません。それがまさに私のポイントです。そして、onPause、onStop、およびonDestroyは状態情報を保存し、多かれ少なかれリソースをGCで利用できるようにする(つまり、ある意味でリソースを破棄する)ため、デストラクタに類似しているため、最後にそれらを呼び出すことは理にかなっていると思います。番号?
Anudeep Bulla 2013

上記で述べたすべては、「スーパーメソッドを最初に呼び出すことは、作成の半サイクルで意味をなす」と私が言ったときの意味とまったく同じです。私は心配していますが、解体業者に類似しているように見える破壊半サイクル法の場合は混乱しています。乾杯
Anudeep Bulla

1

覚えておくべき最も重要なことは、super.onPause()暗黙的にを呼び出すことsetResult(Activity.RESULT_CANCELED)です。ただしsetResult、呼び出すことができるのは1回のみで、以降の呼び出しはすべて無視されます。したがって、何らかの結果を親アクティビティに戻したい場合は、を呼び出す前にsetResult、自分自身を呼び出す必要があります。私が知る限り、それは最大の落とし穴です。super.onPause()


うわー、これは重要なようです。したがって、スーパーメソッドの呼び出しを確実に遅延させる必要がある場合があります。ありがとうございました。
Anudeep Bulla 2013

super.onPause() implicitly calls setResult(Activity.RESULT_CANCELED)。これをどこから手に入れたのか教えてもらえますか?
Vikram 2013

私は混乱していた。setResultを呼び出すのは実際にはfinish()であり、super.onBackPressed()はfinish()を呼び出します。したがって、setResultは必ずsuper.onBackPressed()の前に呼び出す必要があります。super.onPause()によってsetResultが呼び出される状況があるかどうかはわかりませんが、危険を冒したくありません。
Philip Sheard 2013

1

どちらも正しいIMOです

ドキュメントによると

派生クラスは、このメソッドのスーパークラスの実装を呼び出す必要があります。そうでない場合は、例外がスローされます。

Super ドキュメンテーションが明示的にそう言うとき、メソッドは常に呼び出されるべきです。

ただし、スーパーメソッドを呼び出すタイミングを選択できます。

の出所を見る onPause

protected void onPause() {
    getApplication().dispatchActivityPaused(this);
    mCalled = true;
}

したがって、呼び出される前でも後でも問題ありません。あなたは良いはずです。

しかし、ベストプラクティスとして、最初にそれを呼び出す必要があります。

主に保護メカニズムとしてお勧めしsuperます。例外がある場合、インスタンスメソッドは既に呼び出されています。

また、これらの呼び出しを1行目に置くと、メソッドのコードを削除したり、誤ってスーパークラスの呼び出しを削除したりするなど、将来のミスを防ぐのに役立ちます。


質問が最初は完全に明確でなかったとしたら申し訳ありませんが、親切にご覧ください。
Anudeep Bulla 2013

@AnudeepBullaそれは私があなたに説明したものです。どちらでも使用できます。どちらも有効です。
Sunil Mishra 2013

onPause、onStop、およびonDestroyメソッドのカスタム実装は厳密には必要ないことを理解しています。私はそれらなしで十分なアプリを作りました。では、スーパーメソッドは常に呼び出されるべきだとはどういう意味ですか?オーバーライドしなくても、暗黙的に呼び出されます。どちらも機能することも知っています。私はなぜドキュメントがスーパーが最初に呼び出されるべきであると言うのか知りたいです。それでも質問がはっきりしない場合は、「しかし、ベストプラクティスのために、最初にそれを呼び出す必要がある」と言うとき、なぜ説明してください。
Anudeep Bulla 2013

オーバーライドしない場合、メソッドはから呼び出されBase Classますが、オーバーライドする場合は、super他のメソッドを呼び出す必要がありますandroid.app.SuperNotCalledException
Sunil Mishra

1
あなたは誤解しているようです。問題は、電話をかけるかどうかではありません。あなたが指摘したように、あなたがそれらを上書きするなら、あなたはしなければなりません。問題は、いつですか?
Anudeep Bulla 2013

1

あなたはGoogleが方法1を提案していると言いますが、有名なAndroidフレームワークエンジニアであるDianne Hackbornは、そうでなければGoogleフォーラムリンクを参照することを提案しています。

onPause、onStoponDestroyメソッドインスタンスを破棄するときは最後、そしてonCreate、onResumeonStartのメソッドでインスタンスを作成するときは、最初にスーパークラスを呼び出すことは直感的に理解できます。


Dianne Hackbornの投稿へのリンクは重要であり、パターンを確認します。
Nick Westgate 2015年

0

システムの内部でアクティビティを正しい状態にするには、コールバックのスーパーが必要です。

アクティビティを開始し、システムによってonCreateが呼び出されたとします。これをオーバーライドして、たとえばレイアウトをロードできます。ただし、システムフローのために、システムを標準の手順で続行できるように、superを呼び出す必要があります。そのため、呼び出さないと例外がスローされます。

これは、onCreateでの実装とは関係なく行われます。これは、システムの唯一の重要事項です。ANRがない場合は、コールバックに無限ループがあり、アクティビティはそのループでキャッチされます。したがって、システムはコールバックが終了したことを認識し、次のコールバックを呼び出します。

スーパーコールのタイミングが必要な状況は1つだけ知っています。onCreateでテーマやディスプレイなどの標準的な動作を変更する場合は、superを呼び出して効果を確認する前に変更する必要があります。それ以外の場合、私の知る限り、それを呼び出すときに違いはありません。

しかし、それを破る正当な理由がない場合は、コールバックの最初の行にスーパーを置き、その後にコードを続けるのに最適な方法をシステムに実行させることができます。


onCreateのシーケンスは、かなり理解しやすいようです。破壊方法はどうなりますか?onStopと言います。私のonStop実装が、呼び出された場合にスーパーメソッドが解放するリソースの一部を使用するとします。その場合、実装後にスーパーメソッドを呼び出すことが理にかなっています。
Anudeep Bulla 2013

理想的には、これが正しいことです。私たちの活動には、常にスーパークラスが持つリソースなどがあります。また、私の活動に依存しないリソースは、ほとんどの場合、一般的なスーパークラスリソースに依存している可能性があります。最初にリソースを処理し、次にスーパークラスを呼び出して一般的なリソースを処理する方が理にかなっています。なぜGoogleは最初にスーパークラスのメソッドを「呼び出す必要がある」と言うのですか?
Anudeep Bulla 2013

onCreateでアクセスできますが、onDestroyではアクセスできないリソースについてお話しください。
Steve Benett、2013

ユースケースはありません。それがOOPスタイルによってどのように変化するのか疑問に思っています。スーパークラスコンストラクターは、実装前に最初に呼び出され、スーパークラスデストラクターは、実装後に最後に呼び出されます。onPause、onStop、およびonDestroyは厳密にデストラクタではありませんが、同じことを行う傾向がありますよね?少なくともonDestroyとほとんどのonStopも..いいえ?
Anudeep Bulla 2013

コンストラクタ/デストラクタとしてではなく、状態が変化する方法でコールバックを参照してください。すべてのコールバックには、アクティビティの作成(すぐに使用可能)/破棄(対話する最後のチャンス)、またはフォアグラウンド/バックグラウンドに配置するなどの必要があります。システムのフローでリソースを制御できるコールバックがあります。システムはそれがどの状態であるかをチェックし、それに応じて処理します。使用するリソースとシステムが制御するリソースは互いに独立しており、交差はありません。
スティーブベネット2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.