温故而知新:重新认识Activity的生命周期,大厂面试题汇总

  • 子类必须在onCreate中调用 super 方法,也就是super.onCreate, 否则会抛出异常。(尽量保证super方法在子类onCreate方法的第一行)

  • 如果onCreate方法的参数onSaveInstanceState不为空,那么它是Activity最近被系统杀死时保存了你在onSaveInstanceState方法中设置的值,你可以用它来恢复数据。

其他注意事项是你不能在此方法中执行任何耗时的代码,在所有的Activity的生命周期方法中也是如此。

2. onContentChanged

说明:

onContentChanged方法其实来自于Window的Window.Callback接口中的回调方法,Activity实现了该接口,该方法实际上相当于一个hook方法,每当Window的setContentView方法被调用时它就会被调用。

/**

* This hook is called whenever the content view of the screen changes

* (due to a call to

* {@link Window#setContentView(View, android.view.ViewGroup.LayoutParams)

* Window.setContentView} or

* {@link Window#addContentView(View, android.view.ViewGroup.LayoutParams)

* Window.addContentView}).

*/

在onCreate方法中调用的setContentView方法,实际上是会调用Window的setContentView方法,在Activity的源码当中它的实际调用者是PhoneWindow对象,PhoneWindow是Window抽象类的子类,在PhoneWindow的源码中,setContentView方法调用了onContentChanged方法。

也就是说Activity的内容布局发生变化时,就会回调此方法,因此我们可以选择在此方法中进行view的一些初始化操作,比如findViewById()操作,可以放在此方法中进行。不过此方法在实际开发中并不常用,除非你的布局在Activity创建以后会重新设置,此方法或许有用。

3. onStart

说明:

这个方法会在Activity实例被创建的时候,以及经过onStop之后重新返回该Activity时会被调用。来看源码的注释说明:

/**

* Called after {@link #onCreate} — or after {@link #onRestart} when

* the activity had been stopped, but is now again being displayed to the

* user. It will be followed by {@link #onResume}.

*

* Derived classes must call through to the super class’s

* implementation of this method. If they do not, an exception will be

* thrown.

*/

没有啥特别的,就是除了onCreate会调用它之外,也会在onRestart方法之后调用它(此时肯定是被其他ac遮挡状态)。 经过onRestart方法之后再调用onStart后,窗口将会对用户可见,这也就告诉我们如果想要用户更快的看到界面,就不要在onCreate和onStart方法中做过多无关UI的操作。另外不要忘记在子类的onStart方法中调用super.onStart方法(并尽量保证在第一行),否则同样会抛异常。

4. onRestoreInstanceState

说明:

这个方法比较有意思,主要是用来恢复数据的,在一般情况下它不会被调用,只有当这个Activity是被系统杀死并且需要再次展现该Activity的时候会被调用。

/**

* This method is called after {@link #onStart} when the activity is

* being re-initialized from a previously saved state, given here in

* savedInstanceState. Most implementations will simply use {@link #onCreate}

* to restore their state, but it is sometimes convenient to do it here

* after all of the initialization has been done or to allow subclasses to

* decide whether to use your default implementation. The default

* implementation of this method performs a restore of any view state that

* had previously been frozen by {@link #onSaveInstanceState}.

*

* This method is called between {@link #onStart} and

* {@link #onPostCreate}.

*

* @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.

*

*/

该方法会在onStart方法之后,onPostCreate方法之前被调用,它有一个参数savedInstanceState,这是一个Bundle对象,它是在onSaveInstanceState方法中保存数据的对象参数。

当你需要恢复View的状态时你可以选择在onSaveInstanceState方法中为该参数设置值,这样当Activity被系统销毁重建时就可以在onRestoreInstanceState方法的参数中获得该参数来重新恢复你的布局状态。

值得注意的是,在onCreate方法中也有一个savedInstanceState,它跟onRestoreInstanceState方法里的参数区别是,在onCreate方法中的这个参数是可以为空的(首次创建),而对于onRestoreInstanceState方法,只要它被调用,这个参数就一定不为空。

另外实测发现,该方法确实是 “当且仅当Activity被系统杀死,再由系统恢复” 时,才会被调用的,也就是说假如你主动调用了finish方法去干掉它,或者别人调用了finish方法干掉了它,或者是用户主动干掉了它,或者由于异常挂掉了,都不要指望在它重新创建的时候会走onRestoreInstanceState方法,这时重建Activity的时候都不会调用此方法的。经过我自己的手机上的测试,在发生屏幕旋转的时候Activity重建会调用onRestoreInstanceState方法, 因为这种情况系统也会先杀死Activity然后再重新创建。

5. onPostCreate

说明:

此方法会在onStart和onRestoreInstanceState之后调用,当然如果onRestoreInstanceState没有被调用,那么onStart之后会直接调用它。只有当Activity首次创建的时候才会调用它,当过onStop再次回到Activity时并不会执行它。来看它的源码注释:

/**

* Called when activity start-up is complete (after {@link #onStart}

* and {@link #onRestoreInstanceState} have been called). Applications will

* generally not implement this method; it is intended for system

* classes to do final initialization after application code has run.

*

* Derived classes must call through to the super class’s

* implementation of this method. If they do not, an exception will be

* thrown.

*

* @param savedInstanceState If the activity is being re-initialized after

* previously being shut down then this Bundle contains the data it most

* recently supplied in {@link #onSaveInstanceState}. Note: Otherwise it is null.

* @see #onCreate

*/

官方注释说这个方法通常没必要重写,设计意图是为了给系统类使用的,实际中此方法看起来也确实没多大卵用,你可以选择性的使用。此方法携带savedInstanceState参数,同样可以做恢复View操作。重写的话子类同样必须要调用super方法。

6. onStateNotSaved

说明:

/**

* Called when an {@link #onResume} is coming up, prior to other pre-resume callbacks

* such as {@link #onNewIntent} and {@link #onActivityResult}. This is primarily intended

* to give the activity a hint that its state is no longer saved – it will generally

* be called after {@link #onSaveInstanceState} and prior to the activity being

* resumed/started again.

*/

这个方法看起来也没有什么卵用,而且它的调用时机不是严格按照顺序确定的,在一开始的完整流程图中,关于这个方法其实是缺少了一种情况的,当Activity第一次创建的时候,它会在onPostCreate之后被调用,而在Activity经过onStop再返回的时候它的顺序又不是这样的,此时会在onRestart方法之前调用它,但是当我手机锁屏再打开之后它又是在onStart之后调用的。

但不管怎样onStateNotSaved都会保证总是在onResume之前,以及在onNewIntent和onActivityResult之前被调用,这可能是该方法唯一有用的点了吧,可以允许你在onResume或onActivityResult之前的某个时机做一些事情。看了下该方法是在API 23 Android 6.0被加入的。

7. onResume

说明:

这个方法应该很常用了,此方法会在onStart方法之后执行,这是唯一确定的执行顺序,如果是首次创建会执行它,当然当Activity经历onPause或onStop之后也会执行到此方法。如果首次创建时有这几个方法onRestoreInstanceState、onPostCreate、onStateNotSaved,那么onStart会在他们之后执行。

/**

* Called after {@link #onRestoreInstanceState}, {@link #onRestart}, or

* {@link #onPause}, for your activity to start interacting with the user.

* This is a good place to begin animations, open exclusive-access devices

* (such as the camera), etc.

*

* Keep in mind that onResume is not the best indicator that your activity

* is visible to the user; a system window such as the keyguard may be in

* front. Use {@link #onWindowFocusChanged} to know for certain that your

* activity is visible to the user (for example, to resume a game).

*

* Derived classes must call through to the super class’s

* implementation of this method. If they do not, an exception will be

* thrown.

*

*/

官方注释说明明确指出,不能以此方法作为判断标志来确定当前activity是都是对用户可见的,因为可能有其他的系统弹窗在该activity前面,比如系统软键盘(我想官方这里的意思可能是不一定完全对用户可见,但是经过onResume之后setContentView设置的内容就会显示出来)。同样,子类必须调用super方法,否则会报异常。(尽量保证super在第一行)

虽然官方建议onResume不能作为用户可见的依赖方法,但实际当中基本上我们会在此方法中恢复一些之前停止的状态,如恢复之前在onPause中停止的动画、视频播放、Camera预览等,因为只要onResume被调用了说明用户之前的activity回到前台(有可能不是完全可见,只有一部分可见,但用户肯定是能看到它的,至少是部分),从体验角度来讲是需要这样处理的。

此外,不能在onResume方法中做额外的耗时任务,如数据保存数据库,I/O读写等,这将导致Activity的卡顿,或者用户重新回来的时候卡顿,影响交互体验。

8. onPostResume

说明:

此方法跟onPostCreate方法类似,会紧跟在onResume方法之后被调用。

/**

* Called when activity resume is complete (after {@link #onResume} has

* been called). Applications will generally not implement this method;

* it is intended for system classes to do final setup after application

* resume code has run.

*

* Derived classes must call through to the super class’s

* implementation of this method. If they do not, an exception will be

* thrown.

*

*/

同样,从官方的注释说明来看它目前并没有什么卵用。。

9. onAttachedToWindow

说明:

该方法是Window中Wind
ow.Callback接口中的方法,该方法会在window被添加的WindowManager上时被调用。从调用顺序上看,它会在onPostResume方法之后被调用,但是只有Activity首次创建才会调用。

/**

* Called when the main window associated with the activity has been

* attached to the window manager.

* See {@link View#onAttachedToWindow() View.onAttachedToWindow()}

* for more information.

* @see View#onAttachedToWindow

*/

官方注释让看View#onAttachedToWindow()方法,但是我看了下View的这个方法中并没有找到调用Window.Callback的onAttachedToWindow方法,于是后来到DectorView类中终于找到了该方法的回调,我们知道DectorView是最顶层的View,当我们设置给PhoneWindow对象的contentView最终都会被加到DectorView上,当然如果你的Activity没有调用setContentView的话,也是会有默认的DectorView对象的。所以,实际上是DectorView被添加到PhoneWindow时会调用此方法。因此onAttachedToWindow在Activity创建后一定被执行的,并且从该方法开始View才真正被绘制在窗口之上,也是我们最终看到的东西。所以严格意义来讲,经过该方法之后Activity才处于可以与用户进行交互的状态。这也是为什么在阿里的android开发手册当中推荐你在onAttachedToWindow方法之后再去创建显示弹窗。

10. onPause

说明:

此方法也是高频使用的方法,通常在Activity不在前台(被其他Activity的页面完全遮挡,或者部分可见)时被调用。

/**

* Called as part of the activity lifecycle when an activity is going into

* the background, but has not (yet) been killed. The counterpart to

* {@link #onResume}.

*

* When activity B is launched in front of activity A, this callback will

* be invoked on A. B will not be created until A’s {@link #onPause} returns,

* so be sure to not do anything lengthy here.

*

* This callback is mostly used for saving any persistent state the

* activity is editing, to present a “edit in place” model to the user and

* making sure nothing is lost if there are not enough resources to start

* the new activity without first killing this one. This is also a good

* place to do things like stop animations and other things that consume a

* noticeable amount of CPU in order to make the switch to the next activity

* as fast as possible, or to close resources that are exclusive access

* such as the camera.

*

* In situations where the system needs more memory it may kill paused

* processes to reclaim resources. Because of this, you should be sure

* that all of your state is saved by the time you return from

* this function. In general {@link #onSaveInstanceState} is used to save

* per-instance state in the activity and this method is used to store

* global persistent data (in content providers, files, etc.)

*

* After receiving this call you will usually receive a following call

* to {@link #onStop} (after the next activity has been resumed and

* displayed), however in some cases there will be a direct call back to

* {@link #onResume} without going through the stopped state.

*

* _Derived classes must call through to the super class’s

* implementation of this method. If they do not, an exception will be

* thrown._

*/

官方注释说明中提到,当另一个Activity B需要被创建来到Activity A的前台时,只有当Activity A的onPause方法执行完毕后,才会执行Activity B的创建生命周期方法。所以不应该在该方法中做任何耗时任务。点击查看:Activity启动另一个Activity并返回的完整生命周期

onPause方法被调用时,我们应该释放或者停止任何消耗CPU资源的行为,以便下一个Activity能得到快速的切换显示,比如结束或者暂停正在执行的动画、正在播放的视频、Camera预览、正在使用的系统服务(如GPS或其他传感器)等等。如有必要,需要在onPause方法中对任何用户正在编辑的信息进行持久化的保存,以便用户再次回来时能恢复之前的状态。

对系统而言,如果你的应用不是在前台,也就是经过onPause之后的(当然是onPause之后的那个Activity不属于你的应用的情况),会变成一个后台进程,而后台进程在内存不足时会被系统杀死。因此onPause方法是我们保存全局持久化数据的一个重要方法。虽然在onResume之后会调用onSaveInstanceState方法,在onSaveInstanceState方法中也可以来保存数据,但是该方法的时机较晚,主要用来保存一些UI状态的数据。

注意,当调用finish方法或被系统杀死的时候,onPause是不会被调用的。另外子类一定要调用super方法,否则会报异常。(并尽量保证在第一行)还有就是如果被自己Activity show出来的弹窗遮挡部分的话,onPause也是不会被调用的,必须是被其他Activity show出来的弹窗才能满足条件。

11. onSaveInstanceState

说明:

此方法会在Activity被销毁时调用,可以在该方法中进行UI状态的保存,并在onCreate或者onRestoreInstanceState方法中进行恢复。

/**

* Called to retrieve per-instance state from an activity before being killed

* so that the state can be restored in {@link #onCreate} or

* {@link #onRestoreInstanceState} (the {@link Bundle} populated by this method

* will be passed to both).

*

* This method is called before an activity may be killed so that when it

* comes back some time in the future it can restore its state. For example,

* if activity B is launched in front of activity A, and at some point activity

* A is killed to reclaim resources, activity A will have a chance to save the

* current state of its user interface via this method so that when the user

* returns to activity A, the state of the user interface can be restored

* via {@link #onCreate} or {@link #onRestoreInstanceState}.

*

* Do not confuse this method with activity lifecycle callbacks such as

* {@link #onPause}, which is always called when an activity is being placed

* in the background or on its way to destruction, or {@link #onStop} which

* is called before destruction. One example of when {@link #onPause} and

* {@link #onStop} is called and not this method is when a user navigates back

* from activity B to activity A: there is no need to call {@link #onSaveInstanceState}

* on B because that particular instance will never be restored, so the

* system avoids calling it. An example when {@link #onPause} is called and

* not {@link #onSaveInstanceState} is when activity B is launched in front of activity A:

* the system may avoid calling {@link #onSaveInstanceState} on activity A if it isn’t

* killed during the lifetime of B since the state of the user interface of

* A will stay intact.

*

* The default implementation takes care of most of the UI per-instance

* state for you by calling {@link android.view.View#onSaveInstanceState()} on each

* view in the hierarchy that has an id, and by saving the id of the currently

* focused view (all of which is restored by the default implementation of

* {@link #onRestoreInstanceState}). If you override this method to save additional

* information not captured by each individual view, you will likely want to

* call through to the default implementation, otherwise be prepared to save

* all of the state of each view yourself.

*

* If called, this method will occur before {@link #onStop}. There are

* no guarantees about whether it will occur before or after {@link #onPause}.

*

* @param outState Bundle in which to place your saved state.

*

*/

一般情况下它会在onPause方法之后被调用,但是不能指望一定是在onPause方法之后被调用,最简单的情况比如打开一个Activity,然后按back键关闭它,这时系统就不会调用该方法,或者直接调用finish方法也不会调用该方法。当系统内存不足时可能会直接调用该方法,而不会调用其他任何生命周期方法。总之该方法跟生命周期的依赖不是固定的。

目前能确定调用该方法的场景有:按下home键、锁屏、跳转到其他Activity、横竖屏切换。能确定的一点是只要该方法被调用到,那么一定是在onStop之前,跟onPause方法的先后顺序不确定。

实际上即便你不实现该方法,该方法的父类默认实现页会将视图树中拥有id的每个控件的UI状态以及获得视图焦点的id进行保存,并在onRestoreInstanceState方法中来为你恢复每个实例的UI状态。但是如果你有额外的被UI控件持有的信息需要保存,你可能需要重写此方法。

此外,我们应该只在该方法中进行view状态的保存,而不应该依赖该方法做额外的持久化数据保存如数据库保存,上传服务器等等。

12. onStop

说明:

此方法当Activity对用户不可见时被调用,可以在该方法中进行数据持久化保存。

/**

* Called when you are no longer visible to the user. You will next

* receive either {@link #onRestart}, {@link #onDestroy}, or nothing,

* depending on later user activity.

*

* _Derived classes must call through to the super class’s

* implementation of this method. If they do not, an exception will be

* thrown._

*

*/

类似onPause方法,此方法中也可以进行资源的释放,因为经过onStop之后该Activity也不在前台了,有可能是按了Home键或者其他Activity来到了前台。假如是按了Home键或其他app来到前台,那么该Activity所处进程变成后台进程有可能被系统杀死,所以需要释放那些系统共享资源如GPS、Camera,或者暂停动画、视频播放等销毁CPU的资源。同时时我们可以在onPause方法保存用户数据,以做现场恢复用。

在onStop方法之后,要么是经历onDestroy方法销毁Avtivity,要么是会在稍后重新返回Activity执行onRestart方法。

在子类中必须调用super方法,否则会抛出异常。(尽量保证在第一行)

13. onRestart

说明:

此方法是当前Activity被其他Activity完全遮挡再返回时调用,也就是经过onStop之后,此方法之后会紧接着调用onStart方法。

/**

* Called after {@link #onStop} when the current activity is being

* re-displayed to the user (the user has navigated back to it). It will

* be followed by {@link #onStart} and then {@link #onResume}.

*

* For activities that are using raw {@link Cursor} objects (instead of

* creating them through

* {@link #managedQuery(android.net.Uri , String[], String, String[], String)},

* this is usually the place

* where the cursor should be requeried (because you had deactivated it in

* {@link #onStop}.

*

* _Derived classes must call through to the super class’s

* implementation of this method. If they do not, an exception will be

* thrown._

*

*/

官方注释提到如果你使用原生的Cursor对象(而不是通过managedQuery方法),可以在该方法中恢复Cursor请求(因为有可能你在onStop中停止了)Cursor请求。但是我看官方的Cursor#requery()Cursor#deactivate()方法都已经弃用,该方法会导致UI线程的ANR。

同样,如果子类想要覆写此方法的话,要调用super方法,否则抛异常。(并尽量放在第一行)

14. onDestroy

说明:

此方法是Activity被销毁的时候调用,一般是调用了finish方法, 也有可能是系统销毁。

/**

* Perform any final cleanup before an activity is destroyed. This can

* happen either because the activity is finishing (someone called

* {@link #finish} on it, or because the system is temporarily destroying

* this instance of the activity to save space. You can distinguish

* between these two scenarios with the {@link #isFinishing} method.

*

* _Note: do not count on this method being called as a place for

* saving data! For example, if an activity is editing data in a content

* provider, those edits should be committed in either {@link #onPause} or

* {@link #onSaveInstanceState}, not here._ This method is usually implemented to

* free resources like threads that are associated with an activity, so

* that a destroyed activity does not leave such things around while the

* rest of its application is still running. There are situations where

* the system will simply kill the activity’s hosting process without

* calling this method (or any others) in it, so it should not be used to

* do things that are intended to remain around after the process goes

* away.

*

* _Derived classes must call through to the super class’s

* implementation of this method. If they do not, an exception will be

* thrown._

*

*/

ly implemented to

* free resources like threads that are associated with an activity, so

* that a destroyed activity does not leave such things around while the

* rest of its application is still running. There are situations where

* the system will simply kill the activity’s hosting process without

* calling this method (or any others) in it, so it should not be used to

* do things that are intended to remain around after the process goes

* away.

*

* _Derived classes must call through to the super class’s

* implementation of this method. If they do not, an exception will be

* thrown._

*

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值