前天用户体验反馈的一个需求,要求每次进入应用都定位到首页;这个操作很明显不适合放在首页Activity(启动模式为SingleTask)的onResume中,如果对Activity的启动模式和生命周期熟悉,那么很容易想到在onNewIntent里操作就可以了,这样在应用内跳转不至于每次都定位到首页.
可见,对Activity生命周期和启动模式进行一下梳理很有必要.下面主要描述一下Activty的生命周期,以及launchMode对生命周期的影响,onNewIntent,onSaveInstanceState,onRestoreInstanceState方法何时调用.
Activity生命周期图
下面对上图Activity的生命周期进行一下描述
1,启动Activity,系统会先调用onCreate方法,然后调用onStart方法,然后调用onResume方法,此时Activity处于运行状态,此时用户可以看到该Activity对应的界面,界面可以与用户进行交互。
2,当Activity处于onResume状态时,Activity被其他界面未全部覆盖,例如弹出Dialog等,此时系统会调用onPause方法,暂停该Activity,将焦点交给弹出的Dialog,此时用户可以看到部分Activity,有一部分被Dialog遮挡,Activity不可以与用户交互,因为焦点在Dialog上。
3,当Activity处于2状态时,此时取消Dialog,让Activty全部可见,此时系统会调用onResume,让Activity重新获取焦点,重新回到运行状态。
4,当Activity处于onPause状态时,如果此时Activity被全部遮盖,或者退到后台。例如弹出一个全屏的界面将Activity全部遮盖,或者按power按键灭屏,那么系统会调用onStop方法。
5,当Activity处于onResume状态时,如果Activity被全部遮盖或者退到后台,例如按Home按键,按Power按键,或者弹出其他全屏Activity,那么系统会调用onPause,然后调用onStop。
6,当Activity处于onStop状态,也就是在后台的状态,重启启动该Activity,例如从多任务启动,从桌面启动,系统会先先调用onRestart,再调用onStart,再调用onResume,让Activity重新回到运行状态
7,当Activity处于onResume状态时,用户结束当前Activity,例如点击返回键,或者调用finish方法,那么系统先调用onPause,再调用onStop,再调用onDestroy。
8,如果Activity处于后台,也就是onStop状态,那么当Activty被回收,被强制结束时,不会执行onDestory,该Activty会被直接停止掉,再次点击启动时,会重新执行对应的生命周期方法。
9,当Activty处于onResume状态时,Activity被重新状态,例如旋转屏幕,调用recreate方法,系统会先调用onPause,再调用onStop,然后调用onDestroy,该Activty被关闭,系统会立刻重新启动该Activty,调用onCreate,再调用onStart,再调用onResume。
10,当Activty处于onStop状态,也就是在后台,此时切换系统设置,例如字体,语言等。此时Activty不会执行生命周期方法,当再次启动Activty时,会先调用onDestroy,然后重新启动Activty 先调用onCreate,再调用onStart,再调用onResume。
Activity的启动模式 即android:launchMode
Activity有四种启动模式,分别为standard,singleTop,singleTask,singleInstance。该属性在AndroidManifest.xml 中设置。
- <activity
- android:name=".MainActivity"
- android:label="@string/app_name"
- android:launchMode="singleInstance">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
1,standard
该模式为默认的模式,即如果Activity标签没有设置android:lanuchMode,那么launchMode就为standard。在该模式下,每次启动Activity都会创建一个新的实例对象,该模式下允许同一个Activity的不同实例同时存在。
如下图:
第一次启动Activty1,那么会创建一个Task,将Activty1放到Task中,如果在Activty1中,再次启动Activty1,那么会重新创建一个Activty1的实例添加到Task中,如果再启动Activty1,那么再重新创建一个Activity1的实例,再次添加到Task中,此时Task中有三个Activty1的实例对象,点击返回,Activty1的三个实例会一个一个的出栈。
2,singleTop
该启动模式,同一个Activity可以有多个不同的实例对象。当启动Activity时,如果栈顶的Activity是该Activity的一个实例,那么就不会重新创建一个Activity的实例,而是会重新使用栈顶的该Activity的实例对象,此时栈顶的Activity实例会调onNewIntent方法。如果栈顶的Activity实例不是该Activity的实例对象,那么就会重新创建一个Activity的实例对象,将该实例对象添加Task中。
如下图:
启动Activity1,此时会创建一个Task,将Activity1添加到Task中。此时如果再启动Activity1,由于Task顶部的Activity实例就是Activity1的实例,那么不会重新创建Activity1的实例,而是会复用Task顶部的Activty1。如果此时启动Activity2,由于Task顶部的实例为Activity1的实例,同时Task中也没有Activity2的实例,那么会重新创建一个Activity2的实例,将Activity2的实例添加到Task中。此时Task顶部的Activity实例为Activity2。如果再次启动Activity2,由于栈顶的Activity实例就是Activity2的实例,那么不会重新创建Activity2的实例,而是复用Task顶部的Activity2的实例,该实例的onNewIntent方法会被调用。如果此时启动Activity1,由于栈顶的Activity实例为Activity2的实例,那么会重新创建一个Activity1的实例,将该实例添加到Task中。这时Task中Activity1的实例有两个,Activity2的实例有一个。
3.singleTask
该模式下Activity的实例只有一个,在同一个程序内启动该Activity时,如果Task中没有该Activity的实例对象,那么会创建一个新的Activity对象,将对象添加到Task中,若Task中存在该Activity的实例,那么销毁掉在该Activity实例上的所有实例,上该Activity实例成为栈顶的实例,该实例的onNewIntent方法会被调用。
如下图:
启动Activity1,此时会创建一个Activity1的实例,并且添加到Task中,启动Activity2,会创建一个Activty2的实例,并且添加到Task中,启动Activty3,会创建一个Activity3的实例,并将该实例添加到Task中,此时Task中有三个Activity实例。Task顶部的为Activity3的实例,此时如果启动Activity2,由于Task中有Activity2的实例,那么Activity2实例上方的所有实例(Activity3)都会被销毁,此时Activity2成为Task顶部的实例。如果再未启动Activity2时,启动Activity1,由于Task中有Activity1的实例,那么Activity1实例上方的实例都会被销毁,Activity1会成为Task顶部的实例,并且onNewIntent会被调用。
4,singleInstance
该模式下,Activity的实例只有一个,并且运行在一个独立的Task中,该Task中不会有其他Activity的实例。
如下图:
启动Activity1,创建一个Activity1的实例,并且添加到Task中,此时启动Activity2,Activity2的lanuchMode为singleInstance,那么会创建一个新的Task,将Activity2的实例放到新的Task中。此时启动Activity3,Activity3的lanuchMode为非singleInstance,那么会将Activity3的实例添加到与Activity1相同的Task中。如果Activity3的lanuchMode也为singleInstance,那么会重新创建一个新的Task,将Activity3的实例放到新的Task中。如下图:
启动模式对Activity生命周期的影响
可以理解成启动模式不会影响Activity的正常的生命周期,一般只会是涉及到onNewIntent方法的调用,不设置android:lanuchMode或者lanuchMode为standard,那么onNewIntent肯定不会被调用,其他三种模式,可能会调用onNewIntent方法,不是一定被调用。singleTop模式,只要栈顶是要启动的Activity实例,那么onNewIntent就会被调用。singleTask,singleInstance,如果在同一个Task总有对应的Activity实例,那么onNewIntent会被调用。
onSaveInstanceState与onRestoreInstanceState方法的调用
onSaveInstanceState主要是用于保存一些临时数据,当Activity恢复时,可以恢复对应的数据,onRestoreInstanceState当Activity被重新创建时调用,可以从该 方法中恢复一些之前保存过的数据。
onSaveInstanceState一般是在Activity被“打断”的情况下被调用,例如被覆盖,包括全覆盖或者部分覆盖,或者按home退到后台,或者灭屏。另外一种情况就是Activity被重新创建会调用,例如用户在当前Activity旋转屏幕,或者用户调用recreate方法。点击返回键该方法不会被调用。onSaveInstanceState的调用顺序是在onPause之后,onStop之前。
onRestoreInstanceState一般是在Activty被重新创建恢复时会被调用,例如用户切换横竖屏。用户将Activty挂后台,切换系统设置,然后再启动该Activity。