Java 在 onPause、onStop 和 onDestroy 方法中调用超类方法的正确顺序是什么?为什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18821481/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the correct order of calling superclass methods in onPause, onStop and onDestroy methods? and Why?
提问by Anudeep Bulla
I was just going through the Android Developer Site, refreshing on the Activity Life cycle, and in each code example, there is a comment beside the super class methods that says "Always call the superclass method first".
我刚刚浏览了 Android 开发者网站,刷新了 Activity 生命周期,在每个代码示例中,在超类方法旁边都有一条注释,上面写着“始终先调用超类方法”。
Though this makes sense in the creation half cycle: onCreate, onStart and onResume, I'm a little confused as to what is the correct procedure on the destruction half cycle : onPause,onStop,onDestroy.
尽管这在创建半周期中是有意义的:onCreate、onStart 和 onResume,但我对销毁半周期的正确程序是什么感到有些困惑:onPause、onStop、onDestroy。
Destroying the instance specific resources first, before destroying superclass resources that the instance specific resources may depend upon makes sense, not the other way round.But the comments suggest otherwise. What am I missing?
在销毁实例特定资源可能依赖的超类资源之前,首先销毁实例特定资源是有道理的,而不是相反。但评论表明并非如此。我错过了什么?
Edit: Since people seem to be getting confused as to the intent in the question, what I want to know is which of the following is correct? AND WHY ?
编辑:由于人们似乎对问题的意图感到困惑,我想知道以下哪一项是正确的?为什么?
1.Google suggests
1.谷歌建议
@Override
protected void onStop() {
super.onStop(); // Always call the superclass method first
//my implementation here
}
2.The other way
2.另一种方式
@Override
protected void onStop() {
//my implementation here
super.onStop();
}
采纳答案by Vikram
Destroying the instance specific resources first, before destroying superclass resources that the instance specific resources may depend upon makes sense, not the other way round. But the comments suggest otherwise. What am I missing?
在销毁实例特定资源可能依赖的超类资源之前,首先销毁实例特定资源是有意义的,而不是相反。但评论表明并非如此。我错过了什么?
In my opinion: not a single thing.
在我看来:不是一件事。
This answer from Mark (aka CommonsWare on SO) sheds light on the issue: Link - Should the call to the superclass method be the first statement?. But then, you can see the following comment left on his answer:
来自 Mark(又名 CommonsWare on SO)的这个回答阐明了这个问题:链接 - 对超类方法的调用应该是第一条语句吗?. 但是,您可以在他的回答中看到以下评论:
But why official doc says: "Always call the superclass method first" in onPause()?
但是为什么官方文档会在 onPause() 中说:“始终首先调用超类方法”?
Back to square one. Okay, let's look at this from another angle. We know that Java Language Specification does notspecify an order in which the call to super.overridenMethod()
must be placed (or if the call must be placed at all).
回到原点。好吧,让我们从另一个角度来看这个。我们知道 Java 语言规范并没有指定super.overridenMethod()
必须放置调用的顺序(或者是否必须放置调用)。
In case of class Activity, super.overridenMethod()
calls are required and enforced:
在类 Activity 的情况下,super.overridenMethod()
需要调用并强制执行:
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onStop()");
}
mCalled
is set to true in Activity.onStop()
.
mCalled
在 中设置为 true Activity.onStop()
。
Now, the only detail left to debate on is the ordering.
现在,唯一需要讨论的细节是排序。
I also know that both work
I also know that both work
Sure. Look at the method body for Activity.onPause():
当然。查看 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;
}
Whichever way you sandwich the call to super.onPause()
, you'll be ok. Activity.onStop() has a similar method body. But take a look at Activity.onDestroy():
无论您以何种方式将呼叫夹在中间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);
}
Here, the ordering could possiblymatter depending on how your activity is setup, and whether calling super.onDestroy()
would interfere with the code that follows.
在这里,排序可能很重要,具体取决于您的活动是如何设置的,以及调用是否super.onDestroy()
会干扰后面的代码。
As a final word, the statement Always call the superclass method first
doesn't seem to have much evidence to back it up. What's worse (for the statement) is that the following code has been taken from android.app.ListActivity
:
最后,该声明Always call the superclass method first
似乎没有太多证据来支持它。更糟糕的是(对于声明),以下代码取自android.app.ListActivity
:
public class ListActivity extends Activity {
....
@Override
protected void onDestroy() {
mHandler.removeCallbacks(mRequestFocus);
super.onDestroy();
}
....
}
And, from LunarLander sample application included in android sdk:
并且,来自 android sdk 中包含的 LunarLander 示例应用程序:
public class LunarLander extends Activity {
....
@Override
protected void onPause() {
mLunarView.getThread().pause(); // pause game when Activity pauses
super.onPause();
}
....
}
Summary and worthy mentions:
总结和值得一提的:
User Philip Sheard: Provides a scenario where a call to super.onPause()
must be delayed in case of an Activity started using startActivityForResult(Intent)
. Setting the result using setResult(...)
aftersuper.onPause()
will not work. He later clarifies on this in the comments to his answer.
用户 Philip Sheard:提供了super.onPause()
在 Activity 开始使用startActivityForResult(Intent)
. 使用setResult(...)
after设置结果super.onPause()
将不起作用。他后来在对他的回答的评论中澄清了这一点。
User Sherif elKhatib: Explains why letting superclass initialize its resources first and destroy its resources last follows from logic:
用户 Sherif elKhatib:从逻辑上解释为什么让超类首先初始化其资源并最后销毁其资源:
Let us consider a library you downloaded which has a LocationActivity that contains a getLocation() function that provides the location. Most probably, this activity will need to initialize its stuff in the onCreate() which will force you to call the super.onCreate first. You already do that because you feel it makes sense. Now, in your onDestroy, you decide you want to save the Location somewhere in the SharedPreferences. If you call super.onDestroy first, it is to a certain extent possible that getLocation will return a null value after this call because the implementation of LocationActivity nullifies the location value in the onDestroy. The idea is that you wouldn't blame it if this happens. Therefore, you would call super.onDestroy at the end after you're done with your own onDestroy.
让我们考虑您下载的一个库,它有一个 LocationActivity,其中包含一个提供位置的 getLocation() 函数。最有可能的是,此活动需要在 onCreate() 中初始化其内容,这将迫使您首先调用 super.onCreate。你已经这样做了,因为你觉得这是有道理的。现在,在 onDestroy 中,您决定要将 Location 保存在 SharedPreferences 中的某处。如果先调用super.onDestroy,那么一定程度上有可能getLocation在这次调用之后会返回一个空值,因为LocationActivity的实现将onDestroy中的位置值置为空。这个想法是,如果发生这种情况,你不会责怪它。因此,在您完成自己的 onDestroy 后,您将在最后调用 super.onDestroy。
He goes on to point out: if a child class is suitably isolated (in terms of resource dependency) from the parent class, the super.X()
calls need not adhere to any order specification.
他继续指出:如果子类与父类适当地隔离(在资源依赖方面),则super.X()
调用不需要遵守任何顺序规范。
See his answer on this page to read through a scenario where placement of super.onDestroy()
call doesaffect the program logic.
请参阅他在此页面上的回答以通读super.onDestroy()
调用放置确实影响程序逻辑的场景。
From an answer by Mark:
来自马克的回答:
Methods you override that are part of component creation (onCreate(), onStart(), onResume(), etc.), you should chain to the superclass as the first statement, to ensure that Android has its chance to do its work before you attempt to do something that relies upon that work having been done.
Methods you override that are part of component destruction (onPause(), onStop(), onDestroy(), etc.), you should do your work first and chain to the superclass as the last thing. That way, in case Android cleans up something that your work depends upon, you will have done your work first.
Methods that return something other than void (onCreateOptionsMenu(), etc.), sometimes you chain to the superclass in the return statement, assuming that you are not specifically doing something that needs to force a particular return value.
Everything else -- such as onActivityResult() -- is up to you, on the whole. I tend to chain to the superclass as the first thing, but unless you are running into problems, chaining later should be fine.
您重写的方法是组件创建的一部分(onCreate()、onStart()、onResume() 等),您应该将其作为第一条语句链接到超类,以确保 Android 有机会在您之前完成它的工作尝试做一些依赖于已经完成的工作的事情。
您重写的方法是组件销毁的一部分(onPause()、onStop()、onDestroy() 等),您应该首先完成您的工作并将链接到超类作为最后一件事。这样,如果 Android 清理了您的工作所依赖的某些内容,您将首先完成您的工作。
返回 void 以外的其他内容的方法(onCreateOptionsMenu() 等),有时您会链接到 return 语句中的超类,假设您没有专门做一些需要强制特定返回值的事情。
其他一切——比如 onActivityResult()——大体上取决于你。我倾向于将链接到超类作为第一件事,但除非您遇到问题,否则稍后链接应该没问题。
Bob Kernsfrom this thread:
来自此线程的Bob Kerns:
It's a good pattern [(the pattern that Mark suggests above)], but I've found some exceptions. For example, the theme I wanted to apply to my PreferenceActivity wouldn't take effect unless I put it before the superclass's onCreate().
这是一个很好的模式[(马克在上面建议的模式)],但我发现了一些例外。例如, 我想应用到我的 PreferenceActivity 的主题不会生效,除非我把它放在超类的 onCreate() 之前。
User Steve Benettalso brings attention to this:
用户 Steve Benett也注意到了这一点:
I only know one situation, where the timing of the super call is necessary. If you wanna alter the standard behavior of the theme or the display and such in onCreate, you have to do it before you call super to see an effect. Otherwise AFAIK there is no difference at which time you call it.
我只知道一种情况,超级调用的时机是必要的。如果您想在 onCreate 中更改主题或显示等的标准行为,则必须在调用 super 以查看效果之前执行此操作。否则,AFAIK 在您调用它的时间没有区别。
User Sunil Mishraconfirms that order (most likely) does not play a role when calling Activity class' methods. He also claims that calling superclass methods first is considered a best practice. However, I could not corroborate this.
用户 Sunil Mishra确认在调用 Activity 类的方法时,顺序(很可能)不起作用。他还声称首先调用超类方法被认为是最佳实践。但是,我无法证实这一点。
User LOG_TAG: Explains why a call to superclass constructorneeds to be the before everything else. In my opinion, this explanation does not add to the question being asked.
用户 LOG_TAG:解释为什么对超类构造函数的调用需要在其他一切之前。在我看来,这种解释并没有增加所提出的问题。
End note: Trust, butverify. Most of the answers on this page follow this approach to see if the statement Always call the superclass method first
has logical backing. As it turns out, it does not; at least, not in the case of class Activity . Generally, one should read through the superclass' source code to determine if ordering calls to super's methods is a requirement.
尾注:信任,但要验证。此页面上的大多数答案都遵循这种方法,以查看该陈述Always call the superclass method first
是否具有逻辑支持。事实证明,事实并非如此。至少,不是在 Activity 类的情况下。通常,应该通读超类的源代码来确定是否需要对超类的方法进行排序调用。
回答by Sunil Mishra
BOTH are correct IMO
两者都是正确的 IMO
According to the docs
根据文档
Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.
派生类必须调用该方法的超类实现。如果他们不这样做,将引发异常。
Super
method should always be called when documentation explicitly says so.
Super
当文档明确说明时,应始终调用方法。
You can however choose when to call the super method.
但是,您可以选择何时调用 super 方法。
Looking at the source of onPause
看源码 onPause
protected void onPause() {
getApplication().dispatchActivityPaused(this);
mCalled = true;
}
Hence no matter before or after it is called. You should be good.
因此,无论在调用之前还是之后。你应该很好。
But for best practice, you should be calling it first.
但是为了最佳实践,您应该先调用它。
I recommend it mostly as a protection mechanism: if there is an exception then the super
instance method will already have been called.
我主要推荐它作为一种保护机制:如果出现异常,那么super
实例方法将已经被调用。
Also putting these calls on the first line will help you avoid making mistakes in the future such as deleting code in the method and accidentally deleting the call to the super class.
同样将这些调用放在第一行将帮助您避免将来犯错误,例如删除方法中的代码和意外删除对超类的调用。
回答by Steve Benett
The super of the callbacks is needed to put the Activity in the right state internally for the system.
需要回调的 super 才能将 Activity 置于系统内部的正确状态。
Let's say you start your Activity and onCreate is invoked by the system. Now you can override it and e.g. load your layout. But in sake of the system flow you have to call super, that the system can continue with the standard procedure. That's why an exception will be thrown if you don't call it.
假设您启动了 Activity,并且系统调用了 onCreate。现在您可以覆盖它并例如加载您的布局。但是为了系统流程,您必须调用超级,系统才能继续执行标准程序。这就是为什么如果你不调用它就会抛出异常的原因。
This happens independent of your implementation in onCreate. It's only importend for the system. If there would be no ANR you could have an endless loop in any callback and the Activity would be caught in that one. So, the system knows when the callback has been terminated and than calls the next one.
这与您在 onCreate 中的实现无关。它只是系统的importend。如果没有 ANR,您可能会在任何回调中陷入无限循环,而 Activity 将被捕获在该回调中。因此,系统知道回调何时终止,然后调用下一个。
I only know one situation, where the timing of the super call is necessary. If you wanna alter the standard behavior of the theme or the display and such in onCreate, you have to do it before you call super to see an effect. Otherwise AFAIK there is no difference at which time you call it.
我只知道一种情况,超级调用的时机是必要的。如果您想在 onCreate 中更改主题或显示等的标准行为,则必须在调用 super 以查看效果之前执行此操作。否则,AFAIK 在您调用它的时间没有区别。
But to let the system do what it can best put the super in the first line of a callback followed by your code, if you don't have a good reason to break with it.
但是为了让系统做它最好的事情,如果你没有充分的理由打破它的话,最好将 super 放在回调的第一行,然后是你的代码。
回答by Sherif elKhatib
Since (you say) it makes sense to call super onCreate first: Think about it.
因为(你说)首先调用 super onCreate 是有意义的:考虑一下。
When I want to create, My super creates its resources > I create my resources.
当我想创建时,我的超级创建它的资源 > 我创建我的资源。
Inversely: (sort of a stack)
相反:(有点像堆栈)
When I want to destroy, I destroy my resources > My super destroys his resources.
当我想破坏时,我破坏我的资源>我的超级破坏他的资源。
In this sense, it applies to any couple of functions (onCreate/onDestroy, onResume/onPause, onStart/onStop). Naturally, onCreate will create resources and onDestroy will free these resources. By the way, the same proof applies to the other couples.
从这个意义上说,它适用于任何一对函数(onCreate/onDestroy、onResume/onPause、onStart/onStop)。自然地,onCreate 将创建资源,而 onDestroy 将释放这些资源。顺便说一下,同样的证明也适用于其他夫妇。
Let us consider a library you downloaded which has a LocationActivity that contains a getLocation() function that provides the location. Most probably, this activity will need to initialize its stuff in the onCreate() which will force you to call the super.onCreate first. You already do that because you feel it makes sense. Now, in your onDestroy, you decide you want to save the Location somewhere in the SharedPreferences. If you call super.onDestroy first, it is to a certain extent possible that getLocation will return a null value after this call because the implementation of LocationActivity nullifies the location value in the onDestroy. The idea is that you wouldn't blame it if this happens. Therefore, you would call super.onDestroy at the end after you're done with your own onDestroy. I hope this makes a bit sense.
让我们考虑您下载的一个库,它有一个 LocationActivity,其中包含一个提供位置的 getLocation() 函数。最有可能的是,此活动需要在 onCreate() 中初始化其内容,这将迫使您首先调用 super.onCreate。你已经这样做了,因为你觉得这是有道理的。现在,在 onDestroy 中,您决定要将 Location 保存在 SharedPreferences 中的某处。如果先调用super.onDestroy,一定程度上有可能getLocation在这次调用后会返回一个空值,因为LocationActivity的实现将onDestroy中的位置值置为空。这个想法是,如果发生这种情况,你不会责怪它。因此,在您完成自己的 onDestroy 后,您将在最后调用 super.onDestroy。我希望这有点道理。
If the above makes sense, consider that at any moment we have an activity that abides by the above concept. If I want to extend this activity, I will probably feel the same way and follow the same ordering because of the same exact argument.
如果以上有道理,请考虑在任何时候我们都有一个遵守上述概念的活动。如果我想扩展这个活动,我可能会因为相同的参数而有相同的感觉并遵循相同的顺序。
By induction, any activity should do the same thing. Here is a good abstract class for an activity forced to follow these rules:
通过归纳,任何活动都应该做同样的事情。对于被迫遵循这些规则的活动,这是一个很好的抽象类:
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);
}
}
Finally, what if your activity called AnudeepBullaActivity
extends BaseActivity and later on, I want to create SherifElKhatibActivity
that extends your activity? In what order should i call the super.do
functions? It is ultimately the same thing.
最后,如果您的活动称为AnudeepBullaActivity
extends BaseActivity 并且稍后我想创建SherifElKhatibActivity
扩展您的活动怎么办?我应该按什么顺序调用super.do
函数?它最终是一样的。
As for your question:
至于你的问题:
I think that Google's intention is to tell us: Please call the super no matter where. As a general practice of course, call it in the beginning. Google of course has the brightest engineers and developers so they probably done a good job isolating their super calls and not interfering in the child calls.
我认为谷歌的意图是告诉我们:无论在哪里,请调用超级。当然,作为一般的做法,一开始就调用它。谷歌当然拥有最聪明的工程师和开发人员,所以他们可能在隔离他们的超级调用和不干扰子调用方面做得很好。
I tried a bit and it is probably not easy (since it is Google we are trying to prove wrong) to create an activity that would crash simple because of When is super being called.
我尝试了一点,创建一个由于何时调用超级会导致崩溃的活动可能并不容易(因为我们试图证明是谷歌是错误的)。
Why?
为什么?
Anything done in these functions is really private to the Activity class and would never cause any conflict with your subclass. For example (onDestroy)
在这些函数中所做的任何事情对于 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 and mManagedDialogs and mSearchManager are all private fields. And none of the public/protected api will be affected by what is done here.
mManagedCursors 和 mManagedDialogs 和 mSearchManager 都是私有字段。并且所有公共/受保护的 api 都不会受到这里所做的事情的影响。
However, in API 14, dispatchActivityDestroyed was added to dispatch an onActivityDestroyed to the ActivityLifecycleCallbacks registered to your Application. Therefore, any code that would depend on some logic in your ActivityLifecycleCallbacks will have a different outcome based on when you are calling the super. For example:
但是,在 API 14 中,添加了 dispatchActivityDestroyed 以将 onActivityDestroyed 分派到注册到您的应用程序的 ActivityLifecycleCallbacks。因此,任何依赖于 ActivityLifecycleCallbacks 中某些逻辑的代码都会根据您调用 super 的时间而产生不同的结果。例如:
Create an Application Class that counts the number of currently running activities:
创建一个应用程序类来计算当前正在运行的活动的数量:
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) {}
}
The following might not make sense or is not that of a good practice but it is just to prove a point (One might find a more real situation). Create the MainActivity that supposedly goes to GoodBye activity when it is finished and when it is the last activity:
以下可能没有意义或不是一种好的做法,但这只是为了证明一点(人们可能会发现更真实的情况)。创建应该在 GoodBye 活动完成时和它是最后一个活动时转到 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));
}
}
If you call super.onDestroy in the beginning of your onDestroy, the GoodBye activity will be launched. If you call super.onDestroy at the end of your onDestroy, the GoodBye activity will not be launched.
如果在 onDestroy 开始时调用 super.onDestroy,GoodBye 活动将被启动。如果在 onDestroy 结束时调用 super.onDestroy,则不会启动 GoodBye 活动。
Of course, again, this is not the optimal example. However this shows that Google messed up a bit here. Any of the other variables would have not affected your app's behavior. However adding these dispatch to the onDestroy caused the super to somehow interfere with your subclass.
当然,这也不是最佳示例。然而,这表明谷歌在这里有点搞砸了。任何其他变量都不会影响您的应用程序的行为。然而,将这些调度添加到 onDestroy 会导致 super 以某种方式干扰您的子类。
I say they messed for a different reason as well. Not only did they (before api 14) only touch in the super calls what is final and/or private, but they also called different internal functions (private) that really then dispatched the onPause... functions.
我说他们也因为不同的原因搞砸了。他们不仅(在 api 14 之前)只在超级调用中触及最终和/或私有的,而且他们还调用了不同的内部函数(私有),然后真正调度了 onPause... 函数。
For example, performStop
function is the function called that in turn calls the onStop function:
例如,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;
}
Notice that they call the Activity's onStop somewhere in this function. Therefore, they might have as well put all the code (included in super.onStop) before or after the call to onStop and then just notify subclasses about the onStop using empty onStop super functions and without even adding the SuperNotCalledException or checking for this called.
请注意,他们在此函数的某处调用了 Activity 的 onStop。因此,他们也可能在调用 onStop 之前或之后放置所有代码(包含在 super.onStop 中),然后仅使用空的 onStop 超级函数通知子类有关 onStop 的信息,甚至不添加 SuperNotCalledException 或检查此调用。
For this, if they called this dispatch to the ActivityLifeCycle in the performDestroy instead of calling it in the end of super.onDestroy, our activity's behavior would have been the same regardless of when we did call the super.
为此,如果他们在 performDestroy 中将此分派调用到 ActivityLifeCycle 而不是在 super.onDestroy 的末尾调用它,则无论何时调用 super,我们的活动的行为都将相同。
Anyway this is the first thing they do (a bit wrong) and it is only in API 14.
无论如何,这是他们做的第一件事(有点错误)并且仅在 API 14 中。
回答by LOG_TAG
From java perspective here is some solution for this confusion:
从java的角度来看,这里有一些解决这种混淆的方法:
Why does this() and super() have to be the first statement in a constructor?
为什么 this() 和 super() 必须是构造函数中的第一条语句?
The parent class' constructor needs to be called before the subclass' constructor. This will ensure that if you call any methods on the parent class in your constructor, the parent class has already been set up correctly.
父类的构造函数需要在子类的构造函数之前调用。这将确保如果您在构造函数中调用父类上的任何方法,则父类已经正确设置。
What you are trying to do, pass args to the super constructor is perfectly legal, you just need to construct those args inline as you are doing, or pass them in to your constructor and then pass them to super:
你想要做什么,将 args 传递给 super 构造函数是完全合法的,你只需要在你正在做的时候内联构造这些 args,或者将它们传递给你的构造函数,然后将它们传递给 super:
public MySubClassB extends MyClass {
public MySubClassB(Object[] myArray) {
super(myArray);
}
}
If the compiler did not enforce this you could do this:
如果编译器没有强制执行此操作,您可以执行以下操作:
public MySubClassB extends MyClass {
public MySubClassB(Object[] myArray) {
someMethodOnSuper(); //ERROR super not yet constructed
super(myArray);
}
}
It shows that actually, subfields have to be inilialized before the supreclass! Meantime, java requirement "defends" us from specializing the class by specializing what the super constructor argument
它表明实际上,子字段必须在超类之前初始化!同时,java 要求通过专门化超级构造函数参数来“保护”我们免于专门化类
In cases where a parent class has a default constructor the call to super is inserted for you automatically by the compiler. Since every class in Java inherits from Object, objects constructor must be called somehow and it must be executed first. The automatic insertion of super() by the compiler allows this. Enforcing super to appear first, enforces that constructor bodies are executed in the correct order which would be: Object -> Parent -> Child -> ChildOfChild -> SoOnSoForth
在父类具有默认构造函数的情况下,编译器会自动为您插入对 super 的调用。由于 Java 中的每个类都继承自 Object,因此必须以某种方式调用对象构造函数,并且必须首先执行它。编译器自动插入 super() 允许这样做。强制 super 首先出现,强制构造函数体以正确的顺序执行,即:对象 -> 父 -> 子 -> ChildOfChild -> SoOnSoForth
(1) Checking that super is the first statement is not sufficient to prevent that problem. For example, you could put "super(someMethodInSuper());" in your constructor. This attempts to access a method in the superclass before it is constructed, even though super is the first statement.
(1) 检查 super 是第一个语句不足以防止出现该问题。例如,您可以输入“super(someMethodInSuper());” 在你的构造函数中。这会尝试在构造超类之前访问超类中的方法,即使 super 是第一条语句。
(2) The compiler appears to implement a different check which is, by itself, sufficient to prevent this problem. The message is "cannot reference xxx before supertype constructor has been called". Therefore, checking that super is the first statement is not necessary
(2) 编译器似乎实现了一个不同的检查,它本身就足以防止这个问题。消息是“在调用超类型构造函数之前无法引用 xxx”。因此,没有必要检查 super 是第一个语句
Please go through this http://valjok.blogspot.in/2012/09/super-constructor-must-be-first.html
请通过这个http://valjok.blogspot.in/2012/09/super-constructor-must-be-first.html
回答by Philip Sheard
The most important thing to bear in mind is that super.onPause()
implicitly calls setResult(Activity.RESULT_CANCELED)
. But setResult
can only be called once, and all subsequent calls are ignored. So if you want to push any kind of result back to the parent activity, you have to call setResult
yourself, beforeyou call super.onPause()
. That is the biggest gotcha, as far as I know.
要记住的最重要的事情是super.onPause()
隐式调用setResult(Activity.RESULT_CANCELED)
. 但setResult
只能调用一次,所有后续调用都被忽略。所以,如果你想将任何结果返回给父活动的,你得叫setResult
自己,之前你打电话super.onPause()
。据我所知,这是最大的问题。
回答by NickT
You say that Google suggests method 1, however Dianne Hackborn, a well known Android framework engineer suggest otherwise see Google Forum Link.
您说 Google 建议使用方法 1,但是著名的 Android 框架工程师 Dianne Hackborn 建议否则请参阅Google 论坛链接。
It makes intuitive sense to call the super class lastwhen destroyingan instance in the onPause, onStopand onDestroymethods and firstwhen creatingan instance with the methods of onCreate, onResumeand onStart.
在onPause、onStop和onDestroy方法中销毁实例时最后调用超类,以及在使用onCreate、onResume和onStart方法创建实例时首先调用超类是很直观的。