温故而知新:重新认识Activity的生命周期
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中Window.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的创建生命周期方法。所以不应该在该方法中做任何耗时任务。
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请求。但是我看官方的和方法都已经弃用,该方法会导致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._
*
*/
在此方法中需要进行所有资源的释放操作,如释放Camera、GPS, 停止正在运行的Thread、移除正在处理以及尚未处理的Handler消息,停止Service、反注册Receiver等。此方法不能被用做保存用户数据的依赖方法,因为某些情况下(如内存吃紧)系统杀死Activity的宿主进程时不会调用onDestroy。最典型的就是用户从recent used app menu list(最近使用的app菜单列表)中手动杀死Activity时,onDestroy很大概率上基本不会被调用。所以不能将此方法作为Activity销毁的标志依赖方法。
可以使用isFinishing()方法来判断当前activity是否正在销毁过程中,isFinishing()返回true的情况下一般是某个用户主动调用了finish方法,这样在onDestroy方法中就可以判断到底是由系统终止的还是用户主动终止的了。
在子类中必须调用super方法,否则会抛出异常。(尽量保证在第一行)
15. onDetachedFromWindow
说明:
该方法也是Window中Window.Callback接口中的方法,该方法会在Activity从WindowManager上时detach被调用。从调用顺序上看,它会在onDestroy 方法之后被调用。
/**
* Called when the main window associated with the activity has been
* detached from the window manager.
* See {@link View#onDetachedFromWindow() View.onDetachedFromWindow()}
* for more information.
* @see View#onDetachedFromWindow
*/
该方法其实也是DectorView被从PhoneWindow对象上移除时会调用。同样,你不能把它作为Activity被销毁的依赖方法,因为它比onDestroy方法还不靠谱,有些情况下onDestroy方法被调用了,但是此方法不会被调用。
Activity的状态
Activity在系统中是由Activity栈来管理的。当一个Activity启动之后,它会被放在栈顶(压栈)即成为正在运行的那个Activity, 之前的Activity则会保存在栈顶之下并且直到新的Activity被启动之前不会再回到前台。
Activity四种基本状态:
运行状态(running): Activity在屏幕的最前台(位于栈顶), 一般经过onResume方法之后进入该状态。
暂停状态(paused):Activity失去焦点但是仍然可见(有可能是部分可见,如被非全屏或透明的Activity遮挡)。一个被暂停的Activity是完全活跃的(在内存中会保持所有的信息并且仍然被attached在window manager之上),但是在低内存的极端情况下一个暂停的Activity仍然可能被系统杀死。一般经过onPause方法后进入该状态。
停止状态(stoped):被其他Activity完全遮挡,并且对用户完全不可见。虽然此时内存中还会保持它的信息,但这种情况下经常会被系统低内存时优先杀死。一般经过onStop方法后进入该状态。
死亡状态(destroyed):Activity实例已被销毁。通常有几种情况:1.主动调用finish结束掉 2.系统内存不足时杀掉 3.用户手动杀死了应用进程。如果是处于暂停或停止状态的Activity随时有可能被系统或用户杀死。一般进入该状态会经过onDestroy方法(但不确保)。
可见生命周期与前台生命周期
完整生命周期(entire lifetime): 从onCreate() 方法开始到onDestroy()结束的整个过程。要求在onDestroy()中释放所有潜在的执行任务和线程等。
可见生命周期(visible lifetime): 从onStart() 方法开始到onStop()方法被调用之间的过程。在这个过程中用户可以在屏幕上看到该Activity(但不一定可以交互,例如被东西遮挡),需要开发者维护这期间的需要的用户资源,比如在onStart()中注册一个BroadcastReceiver,在Stop()中反注册该BroadcastReceiver。
前台生命周期(foreground lifetime):从 onResume() 方法开始到onPause()方法被调用之间的过程。这时Activity处于所有其它Activity的前台,并且与用户处于可以交互状态。在整个生命周期当中,前后台切换是发生频率最高的,因此不能在这两个方法中执行特别耗时的工作,否则会造成Activity切换时的卡顿,影响体验。
Activity中的其他方法
下面的方法是Activity中的一部分,严格来说这些方法不属于生命周期方法,只是满足特定条件下会被触发,但是有时跟生命周期方法又有着特定关系或者会参与到生命周期当中,你可以重写这些方法来做一些需求处理。
onWindowFocusChanged():当Activity所在的窗口获得或者失去焦点时被触发。也就是当焦点发生变化时触发。这个方法可以用来当做Activity是否对用户可见的标识。该方法是独立于Activity生命周期之外的,但是经过onResume之后一般都会调用走该方法,这时Activity会重新获得焦点,除非有其他dialog或popup弹出。系统的一些弹窗或通知栏面板也会导致该方法被回调。
正常启动Activity时,它的顺序是:*
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
onConfigurationChanged(): 当正在运行的Activity的设备的配置信息发生变化时,由系统调用该方法。你可以在AndroidManifest.xml中为Activity配置该属性,这样配置以后就可以在onConfigurationChanged()方法中获取到这些配置发生变化时的值。如果没有在Manifest文件中配置的项发生,那么系统将会先杀死Activity并重新创建(也就是重新走一遍生命周期)。
其中,可配置的属性如下:
mcc : SIM卡唯一标识IMSI(国际移动用户识别码)中的国家代码,由三位数字组成,中国为460。此项标识mcc代码发生了改变
mnc:SIM卡唯一标识IMSI(国际移动用户识别码)中的运营商代码,由两位数字组成,中国移动TD系统为00,中国联通为01,中国电信为03。此项标识mnc发生了改变
locale:设备的本地位置发生了改变,一般指切换了系统语言
touchscreen:触摸屏发生了改变,这个很费解,正常情况下无法发生,可以忽略它
keyboard:键盘类型发生了改变,比如用户使用了外插键盘
keyboardHide:键盘的可访问性发生了改变,比如用户调出了键盘
navigation:系统导航方式发生了改变,比如采用了轨迹球导航,这个有点费解,很难发生,可以忽略它
screenLayout:屏幕布局发生了改变,很可能是用户激活了另外一个显示设备
fontScale:系统字体缩放比例发生了改变,比如用户选择了一个新字号
uiMode:用户界面模式发生了改变,比如是否开启了夜间模式(API 8添加)
orientation:屏幕方向发生了改变,这个是最常用的,比如旋转了手机屏幕
screenSize:当屏幕的尺寸信息发生了改变,当旋转设备屏幕时,屏幕尺寸会发生变化,这个选项比较特殊,它和编译选项有关,当编译选项中的minSdkVersion和TargetVersion均低于13时,此选项不会导致Activity重启,否则会导致Activity重启(API 13新添加)
smallestScreenSize:设备的物理屏幕尺寸发生改变,这个项目和屏幕的方向没有关系,仅仅表示在实际的物理屏幕的尺寸改变的时候发生,比如用户切换到了外部的显示设备,这个选项和screenSize一样,当编译选项中的minSdkVersion和TargetVersion均低于13时,此选项不会导致Activity重启,否则会导致Activity重启(API 13新添加)
layoutDirection:当布局方向发生改变,这个属性用的比较少,正常情况下无须修改布局的layoutDirection属性(API 17新添加)
对于转屏的情况,测试发现需要配置才可以避免转屏时的重建,少一个也不行,另外现在高版本上的横竖屏切换都会只走一遍生命周期,并没有像以前说的竖切横会走一遍,横切竖会走两遍,可能以前低版本会有这个效果。
onBackPressed():这个方法就是用户按下手机的Back返回键时被触发。默认实现是直接finish掉当前Activity,当然你可以选择覆写该方法来实现你想要的结果。例如,很多app(如微信)采取的效果都是是点击Back键直接回到桌面但是不会finish掉当前Activity,然后再点击应用图标时,会直接回到之前的Activity界面,这种效果是怎么实现的呢?
@Override
public void onBackPressed() {
Intent home = new Intent(Intent.ACTION_MAIN);
home.addCategory(Intent.CATEGORY_HOME);
startActivity(home);
}
这种方式是通过模拟Home键效果强行影响到Back键对Activity生命周期的影响。也可以使用下面的方式:
@Override
public void onBackPressed() {
moveTaskToBack(true);
}
moveTaskToBack()是将当前Activity所在的Task移到后台,同时保留activity顺序和状态。
onKeyDown(): 这个方法是当系统按键被按下时触发,在Activity当中开发中最主要的作用是用来拦截back返回键(虽然KeyEvent中有提供其他按键的Code值,但一般除了back键以外其他系统键基本无法拦截比如Home键、音量键、导航键等)。
常见的两次按下back键退出应用(如今日头条)的监听代码:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
long currentTime = System.currentTimeMillis();
// 如果时间间隔大于2秒,不处理
if ((currentTime - preTime) > 2000) {
Toast.makeText(this, "再按一次退出程序!", Toast.LENGTH_SHORT).show();
//更新时间
preTime = currentTime;
//截获事件,不再处理
return true;
}
}
System.exit(0);
return super.onKeyDown(keyCode, event);
}
其实在onKeyDown()的源码中默认实现会调用onBackPressed(),所以如果你在onKeyDown()方法中拦截了back键的话,onBackPressed()方法就没必要重写了。
onUserInteraction():这个方法是用户与Activity有交互时会被触发,当Activity处于前台时,任意的系统按键(Home键、Back键、音量键等)、Touch事件以及其他会被分发到Activity上的事件触发时会回调这个方法。在Activity的源码中搜索一下你会发现,其实在每个dispatchXXXEvent的方法中会先调用这个方法。官方注释说这个方法是为了让你更加智能的处理通知栏的通知,比如用户与Activity有交互时在该方法中取消通知。该方法会伴随onUserLeaveHint方法一起调用,如果触发onUserLeaveHint一定会先调用该方法。另外,需要注意的是在Touch事件中,只有Action Down才会触发该方法,Action Move和Action Up不会触发。但是对于系统按键按下电源键熄屏/开屏时并不会触发该方法。总之,这个方法为我们提供了一种依据:用户正在与我们的应用进行着交互。
onUserLeaveHint():这个方法是用户主动选择让当前Activity回到后台的时候被调用,比如用户按下Home键回到桌面。注意这个方法只有是由于用户的主动选择而导致当前Activity回到后台时才会调用,由于系统导致而非用户主动选择导致的回到后台的情况不会调用,比如系统来电时会将电话页面带到当前Activity前台,这时不会调用该方法,或者被系统的其他弹窗遮挡也不会触发该方法。还有就是这个方法是针对Activity而不是整个app, 当你在当前Activity启动另一个Activity时,当前Activity会调用该方法。当你调用finish或按back键时,也不会调用该方法,因为这时不是回到后台而是直接干掉了。能确定的一点是该方法被调用时它一定是在onUserInteraction方法之后,并在onPause方法之前被调用。对的,它会伴随onUserInteraction一起调用。如果我们想用这个方法来大致的判断Home键是否被按下,需要在我们自己应用内startActivity的时候给Intent加上标志就可以,这样当你startActivity时当前Activity就不会触发onUserLeaveHint方法,从而可以大致的判断是由于用户按下了Home键导致的。但是这个判断只是大致,并不能精确的判断Activity回到后台只是由于用户按下Home键才导致的,比如我们下拉通知栏,从通知栏中点开一个新的页面也会触发该方法,还有用户在当前Activity打开系统最近使用过的app菜单时也会触发该方法。
onNewIntent():这个方法跟Activity的启动模式有关,只有在AndroidManifest.xml中配置了或或,或者在startActivity的时候Intent添加了或或等标志的时候才可能会调用,关于四种启动模式这里就不展开了。如果一个Activity配置了singleTask或singleInstance,那么只要在栈中已经存在该实例了,再次startActivity打开该Activity时就不会走onCreate而会走onNewIntent方法;如果一个Activity配置了singleTop,再次startActivity打开该Activity时如果该Activity实例已经在栈顶,那么也会走onNewIntent方法而非onCreate。这时的生命周期会按照:onNewIntent()—>onRestart()—>onStart()—>onResume()或者onNewIntent()—>onResume() 的顺序调用(取决于再次回来前是否是完全可见)。需要注意的是,该方法被调用时,通过getIntent方法获取到的还是原始的第一次创建传递的Intent,这也是为啥有的道友在onStart或者onResume方法中死活拿不到新传递的intent的原因了(其实这点还是蛮坑人的),当然官方注释也说明了解决方法,在onNewIntent方法中调用setIntent方法来更新intent就可以了,像下面这样:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
看了下setIntent方法内部是直接赋值的,如果你还想使用最原始的Intent中的信息,最好将原始的Intent保存一份。
onLowMemory():当系统低内存时可能会调用该方法,具体的调用时机未知,一般是系统所有的后台进程都被杀死时,你需要在该方法中进行一些缓存资源或任何非必要资源的释放,在该方法之后系统的垃圾回收器会为你释放这些内存。当然从Android 4.0开始为了避免这种情况,可以选择在AndroidManifest.xml中Application标签上添加属性,这样的话系统会增大app的最大允许使用的内存峰值,可以使用的最大内存值由系统决定的,具体的是在 /system/build.prop文件中的dalvik.vm.heapsize配置值决定的。
onTrimMemory():这个方法是跟onLowMemory()差不多,是从API level 14 Android 4.0开始添加的,只不过这个方法有一个level参数,更加明确了内存不足的状态等级,你可以在该方法中根据不同的内存状态等级来选择清理内存或者资源释放。OnTrimMemory的触发比onLowMemory()会更加的频繁,满足不同等级的条件时都会触发。
onTrimMemory的level参数是一个int数值,代表不同的内存状态, 取值为下面的常量:
TRIM_MEMORY_COMPLETE // 内存不足,并且该进程在后台进程LRU列表的最后一个,马上就要被清理
TRIM_MEMORY_MODERATE // 内存不足,并且该进程在后台进程LRU列表的中部
TRIM_MEMORY_BACKGROUND // 内存不足,该进程已进入后台进程LRU列表
TRIM_MEMORY_UI_HIDDEN // 内存不足,该进程的UI对用户已经不可见,需要清理UI资源
TRIM_MEMORY_RUNNING_CRITICAL // 内存极度不足,无法保持任何后台进程,之后会调用onLowMemory()
TRIM_MEMORY_RUNNING_LOW // 内存不足,低度,需要清理无用内存资源
TRIM_MEMORY_RUNNING_MODERATE // 内存不足,适中,需要清理无用内存资源
finalize():这个方法其实是Java的Object对象的一个方法,之所以在这里列出来是因为可以通过该方法检测你的Activity是否有内存泄漏。当系统虚拟机认为一个对象没有被任何对象引用,也没有被任何线程引用的必要时,垃圾回收器就会回收该对象,这时就会调用此方法。该方法被调用时不一定在UI线程。对同一个对象而言该方法至多只会被调用一次,而且一定是最后被执行的方法,在该方法之后直到垃圾回收器回收该对象之前不会再有其他行为了。该方法的设计意图是为了使得用户可以clean up一些资源。因为一个对象如果被系统回收的话一定会最终调用该方法,而所有的对象都是Object的子类,Activity自然也是Object的子类,因此可借此来检测Activity是否有内存泄漏,可以在该方法中加log, 如果发现你的Activity关闭之后最终该方法没有被调用,那么你就要注意了。
常见Activity生命周期的场景
1.启动Activity:
**onCreate —> onContentChanged —> onStart —> onPostCreate —> onStateNotSaved
—> onResume —> onPostResume —> onAttachedToWindow —> onWindowFocusChanged**
2.启动Activity后按返回键或调finish关闭:
**onUserInteraction —> onUserInteraction —> onWindowFocusChanged —> onPause —> onStop
—> onDestroy —> onDetachedFromWindow —> finalize**
3.按下Home键:
**onWindowFocusChanged —> onUserInteraction —> onUserLeaveHint —> onPause
—> onSaveInstanceState —> onStop**
4.按下Home键再返回来:
**onStateNotSaved —> onRestart —> onStart —> onResume —> onPostResume
—> onWindowFocusChanged**
5.从当前Activity点击按钮启动另一个Activity:
先走当前Activity:
**onUserInteraction —> onWindowFocusChanged —> onUserInteraction —> onUserLeaveHint
—> onPause**
再走另一个Activity:
**onCreate —> onContentChanged —> onStart —> onPostCreate —> onStateNotSaved
—> onResume —> onPostResume —> onAttachedToWindow —> onWindowFocusChanged**
最后再走当前Activity:
onSaveInstanceState —> onStop
6.当前Activity启动另一个Activity后从另一个Activity按back键回来: