当前位置: 移动技术网 > 移动技术>移动开发>Android > Android中Activity生命周期和启动模式详解

Android中Activity生命周期和启动模式详解

2019年07月24日  | 移动技术网移动技术  | 我要评论

activity生命周期经典图解:


按键对生命周期的影响:

back键:

  当我们按back键时,我们这个应用程序将结束,这时候我们将先后调用onpause()->onstop()->ondestory()三个方法。

再次启动app时,会执行oncreate()->onstart()->onresume()

home键:

  当我们打开应用程序时,比如浏览器,我正在浏览nba新闻,看到一半时,我突然想听歌,这时候我们会选择按home键,然后去打开音乐应用程序,而当我们按home的时候,activity先后执行了onpause()->onstop()这两个方法,这时候应用程序并没有销毁。

而当我们从桌面再次启动应用程序时,则先后分别执行了onrestart()->onstart()->onresume()三个方法。

一般activity切换正常生命周期(这里的一般是指启动模式为standard,切换activity时没有加flag标志):

activitya启动activityb:

activitya 的生命周期onpause()->onstop(),

activityb的生命周期oncreate()->onstart()->onresume()。

activityb执行finish返回activitya:

activityb的生命周期onpause()->onstop()->ondestory()

activitya的生命周期了onrestart()->onstart()->onresume()

注意:当activityb定义为dialog样式时,activitya的生命周期是不一样的,

我们给activityb加上theme

<style name="mydialogstyle"> 
   <item name="android:windowbackground">@android:color/transparent</item> 
   <item name="android:windowframe">@null</item> 
   <item name="android:windownotitle">true</item> 
   <item name="android:windowisfloating">true</item> 
   <item name="android:windowistranslucent">true</item> 
   <item name="android:windowcontentoverlay">@null</item> 
   <item name="android:windowanimationstyle">@android:style/animation.dialog</item> 
   <item name="android:backgrounddimenabled">true</item> 
 </style> 

这个时候,activitya启动activityb,b没有完全遮挡a,activityb的生命周期跟刚才一样,但是activitya并没有执行onstop()

还有一点需要特别注意,activity中直接弹dialog,acitivity的生命周期是不会变化的。网上有些说法是会执行onpause(),其实并没有执行!

另外还有几个跟生命周期相关的方法

@override 
 protected void onnewintent(intent intent) { 
   super.onnewintent(intent); 
 } 
 @override 
 protected void onsaveinstancestate(bundle outstate) { 
   super.onsaveinstancestate(outstate); 
 } 
 @override 
 protected void onrestoreinstancestate(bundle savedinstancestate) { 
   super.onrestoreinstancestate(savedinstancestate); 
 } 
 @override 
 public void onconfigurationchanged(configuration newconfig) { 
   super.onconfigurationchanged(newconfig); 
 } 

当应用运行起来后就会开启一条线程,线程中会运行一个任务栈,当activity实例创建后就会放入任务栈中。activity启动模式的设置在androidmanifest.xml文件中,通过配置activity的属性android:launchmode=""设置。

1. standard模式(默认)

我们平时直接创建的activity都是这种模式的activity,这种模式的activity的特点是:只要你创建了activity实例,一旦激活该activity,则会向任务栈中加入新创建的实例,退出activity则会在任务栈中销毁该实例。
standard模式是所启动的activity都是在同一个task容器栈下,不会重新创建新的task容器栈。先压入栈的activity实例按顺序入栈底,后入栈在栈顶,处于栈的顶部activity实例处于活动状态,其他处于非活动状态。按物理返回键,退出当前所处活动状态activity窗口,这样就会从task容器栈中弹出,显示在手机主屏幕上,从而,有非活动状态转换成活动的状态。其次,standard容器栈可能会存在着相同的activity实例,只有没调用一次startactivity方法,就会创建目标activity实例对象压入task容器栈。
如果activity启动顺序为a->b->b->a->d,栈中的acitivy为abbad(最先创建的a位于栈底,最后创建的d位于栈顶)

2. singletop模式

这种模式会考虑当前要激活的activity实例在任务栈中是否正处于栈顶,如果处于栈顶则无需重新创建新的实例,会重用已存在的实例,否则会在任务栈中创建新的实例。
singletop有个不错的用法是防止多次点击创建多个activity,无论start几次,singletop模式能保证栈顶只有一个实例。 如果activity启动顺序为a->b->b->a->d,栈中的acitivy为abad(当b位于栈顶时,再次启动b的时候,b不会重新创建)

3. singletask模式

如果任务栈中存在该模式的activity实例,则把栈中该实例以上的activity实例全部移除,调用该实例的newinstance()方法重用该activity,使该实例处於栈顶位置,否则就重新创建一个新的activity实例。
singletask模式,特别需要注意了。启动的目标activity实例如果已经存在task容器栈中,不管当前实例处于栈的任何位置,是栈顶也好,栈底也好,还是处于栈中间,只要目标activity实例处于task容器栈中,都可以重用该activity实例对象,然后,把处于该activity实例对象上面全部activity实例清除掉,并且,task容器栈中永远只有唯一实例对象,不会存在两个相同的实例对象。所以,如果你想你的应用不管怎么启动目标activity,都只有唯一一个实例对象,就使用这种启动模式。 如果activity启动顺序为a->b->b->a->d,栈中的acitivy为ad(当a再次被启动时,a会被移到栈顶,位于a上面的acitivity全部会出栈)

4. singleinstance模式

当该模式activity实例在任务栈中创建后,只要该实例还在任务栈中,即只要激活的是该类型的activity,都会通过调用实例的newinstance()方法重用该activity,此时使用的都是同一个activity实例,它都会处于任务栈的栈顶。此模式一般用于加载较慢的,比较耗性能且不需要每次都重新创建的activity。

singleinstance启动模式,简单说就是可以共享某个activity。比如,应用1的任务容器栈中创建了mainactivity实例,应用2也要激活mainactivity,则不需要创建mainactivity实例,直接可以公用mainactivity实例。 尤其值得注意:应用1启动mainactivity,按home键;打开应用2启动应用1的mainactivity实例。在按home键,打开应用1,这时候应用1的界面是应该是处于mainactivity界面实例。 singleinstance的一个任务栈中只有一个activity,并保证不再有其他activity实例进入。

特别需要注意的生命周期onnewintent

当一个activity被start,而不需要重新创建时,就会执行onnewintent生命周期。如果一个activity的启动模式是singletask,我们可以在onnewintent中执行一些刷新操作等。

我们一般会把mainacitivy设置为singletask,除了保证mainactivity的唯一,还可以利用singletask的特性做一些清理工作。自动管理栈,销毁无用的acitivity.

intent flags

 flags: 表示intent的标志位,常用于activity的场景中,它和activity的启动模式有着密切的联系。

下面列举的是和本文主题相关的flags属性:

intent.flag_activity_new_task (默认)

默认的跳转类型,它会重新创建一个新的activity,不过与这种情况,比如说task1中有a,b,c三个activity,此时在c中启动d的话,如果在androidmanifest.xml文件中给d添加了affinity的值和task中的不一样的话,则会在新标记的affinity所存在的task中压入这个activity。如果是默认的或者指定的affinity和task一样的话,就和标准模式一样了启动一个新的activity.

flag_activity_single_top这个flag就相当于启动模式中的singletop,例如:原来栈中结构是a b c d,在d中启动d,栈中的情况还是a,b,c,d。

flag_activity_clear_top这个flag就相当于启动模式中的singletask,这种flag启动的activity会把要启动的activity之上的activity全部弹出栈空间。例如:原来栈中的结构是a b c d ,从d中跳转到b,栈中的结构就变为了a b了。

flag_activity_brought_to_front

这个网上很多人是这样写的。如果activity在task存在,拿到最顶端,不会启动新的activity。这个有可能会误导大家! 他这个flag其实是这个意思!比如说我现在有a,在a中启动b,此时在a中intent中加上这个标记。此时b就是以flag_activity_brought_to_front方式启动,此时在b中再启动c,d(正常启动c,d),如果这个时候在d中再启动b,这个时候最后的栈的情况是 a,c,d,b。如果在a,b,c,d正常启动的话,不管b有没有用flag_activity_brought_to_front启动,此时在d中启动b的话,还是会变成a,c,d,b的。

flag_activity_no_user_action

onuserleavehint()作为activity周期的一部分,它在activity因为用户要跳转到别的activity而要退到background时使用。比如,在用户按下home键,它将被调用。比如有电话进来(不属于用户的选择),它就不会被调用。
那么系统如何区分让当前activity退到background时使用是用户的选择?

它是根据促使当前activity退到background的那个新启动的activity的intent里是否有flag_activity_no_user_action来确定的。
注意:调用finish()使该activity销毁时不会调用该函数

flag_activity_no_history

意思就是说用这个flag启动的activity,一旦退出,它不会存在于栈中,比如原来是a,b,c这个时候再c中以这个flag启动d的,d再启动e,这个时候栈中情况为a,b,c,e。

activity相关属性taskaffinity

activity 中的 android:taskaffinity 这个属性介绍:
activity为task拥有的一个affinity。拥有相同的affinity的activity理论上属于相同的task(在用户的角度是相同的“应用程序”)。task的affinity是由它的根activity决定的。 

affinity决定两件事情——activity重新宿主的task(参考allowtaskreparenting特性)和使用flag_activity_new_task标志启动的activity宿主的task。

默认情况,一个应用程序中的所有activity都拥有相同的affinity。捏可以设定这个特性来重组它们,甚至可以把不同应用程序中定义的activity放置到相同的task中。为了明确activity不宿主特定的task,设定该特性为空的字符串。

如果这个特性没有设置,activity将从应用程序的设定那里继承下来(参考<application>元素的taskaffinity特性)。应用程序默认的affinity的名字是<manifest>元素中设定的package名。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网