在onPause、onStop和onDestroy方法中调用超类方法的正确顺序是什么?为什么?

101

我只是在浏览Android开发者网站,重新了解Activity生命周期,在每个代码示例中,都有一个注释说明超类方法旁边的“始终先调用超类方法”。

尽管在创建阶段(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
我在关闭方法的第二阵营。我在启动方法的第一阵营。 - danny117
1
这就是重点。只是不明白为什么使用方法1来进行关闭操作是有意义的。 - Anudeep Bulla
7个回答

118
在销毁实例特定资源之前,先销毁实例特定资源可能依赖的超类资源是有意义的,而不是相反。但是评论表明情况并非如此。我错过了什么?
在我看来:没有任何问题。
Mark(SO上的CommonsWare)的答案阐明了这个问题:链接-调用超类方法应该是第一条语句吗?。但是,您可以看到在他的回答中留下了以下评论:
但为什么官方文档在onPause()中说:“始终首先调用超类方法”?
回到起点。好的,让我们从另一个角度来看待这个问题。我们知道Java语言规范没有指定调用super.overridenMethod()的顺序(或者是否必须放置调用)。
在Activity类的情况下,需要并且被强制执行super.overridenMethod()的调用:
if (!mCalled) {
    throw new SuperNotCalledException(
        "Activity " + mComponent.toShortString() +
            " did not call through to super.onStop()");
}

mCalledActivity.onStop() 中被设置为 true。

现在,唯一需要讨论的细节是顺序。

我也知道两者都可以工作

当然。查看 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()是否会干扰后续代码。

最后,声明始终首先调用超类方法似乎没有太多证据支持。更糟糕的是(对于该声明而言),以下代码来自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: 提供了这样一种情况,即在使用startActivityForResult(Intent)启动活动时必须延迟调用super.onPause()。在super.onPause()之后使用setResult(...)将无效。他在回答评论中对此进行了澄清。

用户Sherif elKhatib:解释了让父类先初始化其资源并在最后销毁其资源的逻辑:

我们考虑一个您下载的库,其中包含一个LocationActivity, 它包含一个getLocation()函数来提供位置。 大多数情况下,此活动需要在onCreate()中进行初始化,这将迫使您首先调用super.onCreate。 您已经这样做,因为您觉得这是有意义的。现在,在您 onDestroy中,您决定要将位置保存在SharedPreferences中。如果您首先调用super.onDestroy,则可以在某种程度上通过 getLocation将返回一个空值在此调用之后,因为LocationActivity 在onDestroy中将位置值变为null。这个想法是你不会责怪它如果这种情况发生了。因此,您应该在完成自己的onDestroy后最后调用super.onDestroy。

他接着指出:如果子类与父类相比有足够的隔离度(资源依赖性),则super.X()调用不需要遵守任何顺序规定。

请查看此页面上他的答案,以了解放置super.onDestroy()调用会影响程序逻辑的情况。

来自Mark的答案:

你重写的组件创建方法(onCreate()、onStart()、onResume()等),应该将超类作为第一条语句链接起来,以确保Android在您尝试依赖于完成的工作之前有机会完成其工作。

你重写的组件销毁方法(onPause()、onStop()、onDestroy()等),应该先执行你的任务,然后在最后链接到超类。这样,在Android清理某些你的任务依赖的东西时,你将首先完成你的任务。

返回值不是void的方法(onCreateOptionsMenu()等),有时你会在return语句中链接超类,假设你没有特别需要强制特定返回值的操作。

其他一切--例如onActivityResult()--基本上取决于你。我倾向于首先链接超类,但除非你遇到问题,稍后链接也可以。

Bob Kerns来自这个帖子

这是一个很好的模式[(Mark上面建议的模式)], 但我发现有些例外。例如,我想应用于我的PreferenceActivity的主题如果不将其放在超类的onCreate()之前就不会生效。

User Steve Benett也引起了注意:

我只知道一种情况,在其中调用super的时机是必要的。如果您想在onCreate中更改主题或显示等的标准行为,则必须在调用super之前执行此操作才能看到效果。否则,在我的理解中,无论何时调用它都没有区别。

User Sunil Mishra确认了顺序(最可能)对调用Activity类方法时没有影响。他还声称先调用超类方法被认为是最佳实践。但是,我无法证实这一点。

User LOG_TAG:解释了为什么在所有其他内容之前需要调用超类的构造函数。在我看来,这个解释并没有增加问题的答案。

结论:信任,但是要验证。本页大部分答案都采用这种方法来查看语句“始终首先调用超类方法”是否具有逻辑依据。事实证明,在Activity类的情况下,它没有;一般来说,应该阅读超类的源代码以确定对super方法的调用顺序是否是必需的。


2
哇,感谢您的指引。这个和@Sherif的回答都提供了重要的上下文信息。 如果你们中的任何一个人能够总结一下这个页面上的答案,我会将其标记为已接受。请包括: 1.此页面上的答案。 2.@Philip在此页面上的答案。 3.@CommonsWare在此页面上的答案。 4.这个讨论 我可以这样做,但我不想因为你们出色的回答而获得荣誉。谢谢! - Anudeep Bulla
你好。@Sherif不想总结一下,你能否请您总结一下? - Anudeep Bulla
@AnudeepBulla 你好,Anudeep,请给我一天的时间。我会在我的回答中添加相关材料,并在这里给您留言。 - Vikram
@AnudeepBulla 我已经添加了一个摘要。如果我漏掉了什么,请告诉我。 - Vikram
因此,我不明白为什么“始终首先调用超类方法”是最佳实践。或者为什么文档这样说,如果它们确实这样说的话。 - getsadzeg
显示剩余2条评论

13

由于(你说)先调用超类onCreate有意义:请思考一下。

当我想创建时,我的超类会创建它的资源 > 我创建我的资源。

反过来的情况:(一种堆栈)

当我想要销毁时,我会销毁我的资源 > 我的超类会销毁它的资源。


在这个意义上,它适用于任何一对函数(onCreate/onDestroy、onResume/onPause、onStart/onStop)。自然地,onCreate将创建资源并且onDestroy将释放这些资源。顺便说一下,相同的证明也适用于其他一对函数。

让我们考虑你下载了一个库,其中包含一个LocationActivity,该活动包含一个getLocation()函数,用于提供位置信息。很可能,这个活动需要在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的意图是告诉我们:无论何时都请调用super。作为一般惯例,当然要在开头调用它。 Google当然拥有最聪明的工程师和开发人员,所以他们可能已经很好地隔离了他们的超级调用并且不会干扰子类调用。

我尝试了一下,可能不容易(因为我们正在试图证明谷歌是错误的)创建一个由于调用super的时间不同而崩溃的活动。

为什么?

在这些函数中执行的任何操作都是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中,dispatchActivityDestroyed被添加到dispatchActivityDestroyed上,以向注册到您的应用程序的ActivityLifecycleCallbacks分派onActivityDestroyed。因此,任何依赖于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) {}
}
以下内容可能有些不太合理,但只是为了证明一个观点(更真实的场景可能会出现),创建MainActivity,当它完成时,它应该转到GoodBye活动,并且当它是最后一个活动时:
@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 ...函数。

例如,performStop函数是所调用的函数,这个函数进而调用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;
}

注意到在这个函数中调用了Activity的onStop方法。因此,他们可以把所有包含在super.onStop中的代码放在onStop被调用之前或之后,然后只需使用空的onStop super函数通知子类关于onStop的情况,甚至不需要添加SuperNotCalledException或者检查是否有调用发生。

为了实现这一点,如果他们在performDestroy中调用了ActivityLifeCycle的dispatch,而不是在super.onDestroy结束时调用,那么我们的activity行为将不受调用super的时间影响。

总之,这是他们做的第一件事(有点错误),而且仅适用于API 14。


问题从来不是为什么最后调用super.onDestroy()有意义。我喜欢你的库示例,正是我想传达的。在销毁半周期中最后调用超级方法,就像在堆栈中一样,可以防止数据意外丢失,这点我完全同意。问题是,鉴于上述前提,为什么Google坚持首先调用超级方法?我问这个问题是因为我认为也许我和你看待这个问题的方式完全不同。干杯 - Anudeep Bulla
哦,我没看到谷歌建议和其他方法:p!听着,我要尝试创建一个活动,如果你首先调用onDestroy,它将崩溃。你也应该尝试一下。干杯 - Sherif elKhatib
@AnudeepBulla 你可以检查我的编辑。顺便说一下,你可以停止尝试了。super.on可能永远不会导致你的活动崩溃。 - Sherif elKhatib
哇,感谢您的指引。这个和@User的回答都提供了重要的上下文信息。 如果你们中的任何一个人能够总结一下这个页面上的答案,我会将其标记为已接受。请包括: 1.此页面上的答案。 2.@Philip在此页面上的答案。 3.@CommonsWare在此页面上的答案。 4.这个讨论 我可以这样做,但我不想因为你们出色的回答而获得荣誉。谢谢! - Anudeep Bulla
@AnudeepBulla 不用谢。我不确定我们将如何决定谁发布最终的写作成果。 - Vikram
我还没有检查这些其他的东西。我很喜欢在这里发现的东西:P。谢谢。@user2558882,你可以根据Anudeep的要求编辑你的答案。 - Sherif elKhatib

4

你说谷歌建议使用方法1,但是著名的Android框架工程师Dianne Hackborn提出了不同的建议,请参见Google Forum Link

onPause、onStop和onDestroy方法中销毁实例时,最好先调用父类的destroy方法;在使用onCreate、onResume和onStart方法创建实例时,最好后调用父类的create方法,这样更符合直觉。


Dianne Hackborn的帖子链接很重要,它确认了这种模式。 - Nick Westgate
这是最好的答案。 - Jones G

1

我认为两种都是正确的

根据文档

派生类必须调用超类的此方法实现。 如果不这样做,将抛出异常。

当文档明确要求时,应始终调用Super方法。

但您可以选择何时调用超级方法。

查看onPause的源代码

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

因此,无论在之前还是之后都称为它。你应该做得很好。
但是为了最佳实践,你应该首先调用它。
我主要推荐它作为一种保护机制:如果有异常,则超级实例方法已经被调用。
此外,将这些调用放在第一行将帮助你避免未来犯错误,例如在方法中删除代码并意外删除对超类的调用。

如果第一次提问不够清晰,我很抱歉。请现在再看一下。 - Anudeep Bulla
@AnudeepBulla 这就是我向你解释的内容。你可以使用其中任何一个。两者都是有效的。 - Sunil Mishra
据我了解,不一定需要自定义实现onPause、onStop和onDestroy方法。我已经制作了很多应用程序而没有这些方法。那么你所说的“超级方法”应该总是被调用是什么意思呢?即使不重写,它们也会被隐式调用。我也知道两种方法都可以。我想知道为什么文档中说应该首先调用super。如果问题还不明显,请解释一下为什么当你说“但出于最佳实践,你应该首先调用它”时? - Anudeep Bulla
如果您不进行重写,则方法将从“基类”中调用,但如果您进行了重写,则需要调用“super”,否则您将会遇到“android.app.SuperNotCalledException”。 - Sunil Mishra
1
你似乎误解了。问题不在于是否调用,正如你所指出的,如果你覆盖它们,你必须要调用。问题是什么时候调用? - Anudeep Bulla
我仍然希望等待更好的答案。感觉不太对,谷歌的精英们会要求我们首先调用超级方法,只是因为我们可能会意外删除它们。 :) - Anudeep Bulla

1

从Java的角度来看,这里有一些解决这种困惑的方案:

为什么this()和super()必须是构造函数中的第一个语句?

父类的构造函数需要在子类的构造函数之前被调用。这将确保如果您在构造函数中调用任何父类的方法,则父类已经正确设置。

您正在尝试做的事情,即将参数传递给超级构造函数是完全合法的,您只需要像您正在进行的那样内联构造这些参数,或者将它们传递到您的构造函数中,然后将它们传递给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);
        }
}

它表明实际上,在初始化超类之前必须初始化子字段!同时,Java的要求通过指定超级构造函数参数来“保护”我们免受类特化的影响。
在父类具有默认构造函数的情况下,编译器会自动为您插入对super的调用。由于Java中的每个类都继承自Object,因此必须以某种方式调用对象构造函数,并且必须首先执行。编译器自动插入super()允许这样做。强制super首先出现,强制构造函数体按正确顺序执行,即:Object->Parent->Child->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
你上面说的一切正是我所说的“在创建半周期中首先调用超级方法是有意义的”的意思。但是在销毁半周期方法方面,我感到担忧和困惑,因为它们似乎更类似于析构函数。干杯! - Anudeep Bulla

1
需要翻译的内容:最重要的是要记住,super.onPause()隐式调用了setResult(Activity.RESULT_CANCELED)。但是setResult只能被调用一次,所有后续的调用都会被忽略。因此,如果你想将任何类型的结果返回给父活动,必须在调用super.onPause()之前自己调用setResult。据我所知,这是最大的陷阱。

哇,这似乎很重要。所以有一种情况,你绝对必须延迟调用超级方法。谢谢。 - Anudeep Bulla
super.onPause() 隐式调用了 setResult(Activity.RESULT_CANCELED)。请问您获取这段内容的来源是什么? - Vikram
我感到困惑。实际上是finish()调用了setResult,而super.onBackPressed()调用了finish()。因此,在调用super.onBackPressed()之前必须先调用setResult。我不确定是否有任何情况会导致super.onPause()调用setResult,但我宁愿不冒险。 - Philip Sheard

0

回调函数的super是必要的,以便将Activity在系统内部置于正确的状态。

假设您启动了Activity并且系统调用了onCreate。现在您可以重写它并加载您的布局等。但为了系统流程,您必须调用super,以便系统可以继续标准过程。如果您不调用它,就会抛出异常。

这与您在onCreate中的实现无关。这仅对系统很重要。如果没有ANR,您可以在任何回调中有一个无限循环,并且Activity将被卡在其中。因此,系统知道回调何时已终止,然后调用下一个回调。

我只知道一种情况,需要调用super的时间。如果您想在onCreate中更改主题或显示的标准行为等,则必须在调用super之前执行此操作才能看到效果。否则,据我所知,在何时调用它没有区别。

但是,为了让系统发挥最佳作用,请将super放在回调的第一行,然后是您的代码,除非您有充分的理由打破它。


在onCreate中的顺序似乎非常容易理解。那么在销毁方法中会发生什么呢?比如说onStop。假设我的onStop实现使用了一些如果调用则释放的超级方法资源。那么在我的实现之后调用超级方法是有意义的。 - Anudeep Bulla
理想情况下,应该是这样的,对吧。我们的活动总是会拥有超类的资源,而且还会有一些额外的资源。而那些与我的活动无关的资源,在大多数情况下可能会依赖于超类的共享资源。先处理我的资源,然后再调用超类来处理共享资源更合理。那么为什么谷歌说我们“应该”先调用超类的方法呢? - Anudeep Bulla
你在说哪个资源,可以在onCreate中访问但无法在onDestroy中访问? - Steve Benett
我没有使用案例,只是想知道它与面向对象编程风格的区别。超类构造函数在你的实现之前首先被调用,而超类析构函数在你的实现之后最后被调用,对吗?onPause、onStop和onDestroy不是严格的析构函数,但它们往往做相同的事情,对吗?至少onDestroy和大多数情况下也包括onStop... 对吗? - Anudeep Bulla
不要将状态改变的回调视为构造函数/析构函数。每个回调都有它的需求,例如创建(准备好使用)/销毁(最后一次交互)一个Activity或将其置于前台/后台。回调存在的目的是让您在系统流程中控制资源。系统只是检查它处于哪个状态并相应地处理。您使用的资源和系统控制的资源是彼此独立的,不会发生交集。 - Steve Benett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接