Analysis of Activity startup mode in "Android In-depth Analysis"

Foreword:

      The startup mode of Activity is a problem that is both basic and easy to ignore, but there is a deep understanding of this problem, which is very helpful for programmers to write a stable and efficient Android program. Today, under the guidance of Brother B, we have a good understanding of the Activity startup mode. , Intent Flags has done a good research, so to speak, if you are not familiar with or understand the startup mode of Activity or how to use Flags, you will definitely be troubled in actual development in the future, come back and re-learn this Section, for example: Why did the client written by someone crash, and there are still one or even N interfaces of the application under it. If you are familiar with and understand this chapter accurately, you will not make this mistake.

Exploration process:

     ①What   is a stack

     ②    Activity stack

     ③   Task

     ④  Activity startup mode

     ⑤   Activity stack and Task contact

     ⑥  Intent Flags 

     ⑦   Activity related attributes taskAffinity

 1. What is a stack

1.1    stack

       The stack is a commonly used data structure. The stack only allows access to the elements at the top of the stack. The stack is like a bullet shuttle (as shown in the figure), and only the top of the stack can be fetched each time. Access its top element of the stack, so as to protect other elements below the top element of the stack. "First-in, last-out" or "last-in, first-out" is a major feature of the stack. The elements of the advanced stack always wait until the elements pushed later are popped out of the stack. Recursion is to use the system stack, temporarily save the temporary results, and protect the temporary results.

 

1.2    Define the stack (Stack)

      Definition of a stack A stack is a linear list that restricts insertion and deletion operations to only one end of the list.

(1) The end of the insertion and deletion is usually called the top of the stack (Top), and the other end is called the bottom of the stack (Bottom).

(2) When there are no elements in the list, it is called an empty stack.

(3) The stack is a Last In First Out (Last In First Out) linear table, referred to as a LIFO table. The modification of the stack is carried out according to the principle of last in, first out. The "latest" element in the current stack is always deleted (unstacked) each time, that is, the last element inserted (pushed onto the stack), and the first inserted is placed at the bottom of the stack, and cannot be popped until the end.

 

1.3   stack operations : push stack, pop stack

 

2. Stack in Activity

       The management of Android is mainly carried out through the Activity stack. When an Activity is started, the system will push it into a specific stack according to its configuration, and the system is in a running state. When the user clicks back or FINISH() the Activity, it will be pushed out of the stack and then destroyed. According to the life cycle of the Activity, it can be known that if the Activity in the currently displayed stack is not popped off the stack (ie Call the ondestory method of Activity), then when a new Activity is opened through Intent, the newly opened Activity will be pushed to the top of the stack. As shown in the following figure (1)

 

                                                                   figure 1)

3.   Task

       Task is the task stack of Activity. In short, it is a collection of Activity components gathered together in a stack mode, which records the user's behavior. (Only mention it and the startup mode of Activity)

 

4. Activity startup mode

Attribute: android:launchMode  

Function: Determine how the Activity starts through the launchMode attribute of the activity in the main configuration file Android Manifest.xml.

描述:这里有四种模式,与Intent对象中的Activity Flags的属性(FLAG_ACTIVITY_*变量)共同作用,来决定Activity如何启动来处理Intent。

四种模式:

    ①   "standard"  --默认模式
    ②   "singleTop"
    ③   "singleTask"
    ④   "singleInstance"

以下举例说明它们的区别:

A.   standard:

       Activity的默认加载方法,该方法会启动创建一个新的activity实例,同时将该实例压入到栈中(不管该activity是否已经存在在Task栈中,都是采用new操作),并调用这个新Activity的OnCreate()方法。。

例如: 栈中顺序是A B CD ,此时D通过Intent跳转到A,那么栈中结构就变成 A B C D A ,点击返回按钮的 显示顺序是 D C B A,依次摧毁。如下图(2)

       一句话记忆:无论栈中是否已经创建过,它都会创建一个新的并置于栈顶并显示,调用oncreate方法。

       使用场景:默认的Activity的启动模式。

                                                       图(2) 

B.   singleTop:

       假设栈内已存在A B C D

       singleTop模式下,分以下两种情况。

1)    当前App应用展示的是D或者栈顶是D,如果这个时候通过Intent需要打开D,那么不会重新创建一个新的D实例,而是调用栈顶的D,并调用它的onNewIntent方法(注意不是oncreate方法,只有创建一个新的实例Activity才会调用Oncreate方法)所以栈中的结构依旧为A B C D。如下图(3)

                                                      图(3)

       思考: 那么,让我们想想,这种情况什么时候会发生呢?好像有点矛盾,当前的显示的或者栈顶的activity,通过Intent或者打开同样的activity,有这种用法和必要吗?

      古语有云:万物皆有其法,android提供了这种用法,那么一定有其道理,至于如何应用和怎样应用,那么有待读者验证,在这里我们只是抛砖引玉,不过可以提供一个这样的场景论证其有效性。

      比如:当前的app栈顶为A,这时候,突然来了个消息通知,这个消息通知需要通过Intent去打开A,那么我们点击这个消息通知打开A的时候,此场景就复现了,它将不会创建一个新的A,而是复用栈顶的A,并执行onNewIntent方法。

2)     当前App应用展示的是D或者栈顶是D,如果这个时候需要打开B,那么由于B不处于栈顶,所以会新建一个B实例并压入到栈中,并调用新创建B的onCreate方法,结构就变成了A B C D B。如下图(4)

                                                     图(4)

      一句话记忆:只有需要打开的A在栈顶,那么不会创建一个新的A,并调用onNewIntent方法,如果需要打开的A不在栈顶,那么不论A在栈中有还是没有,都会创建一个新的A放入栈顶,并执行onCreate方法。

 C.   singleTask:

       singleTask模式下,Task栈中有且只能有一个对应Activity的实例。

例如:当前栈的结构为:A BC D。

       此时D通过Intent打开B,则栈的结构变成了:A B。其中的C和D被栈弹出销毁了,也就是说位于B之上的实例都被销毁了。而不会创建一个新的B实例,而是使用栈中原有的B,此时调用原B的onNewIntent()方法。如下图(5),(6)

                                                  图(5)

                                                    图(6)

       经验谈:此模式较为常见,在activity栈中,因为应用需要,通常需要打开多个相同或者不同的Activity,那么这样,Activity栈会越来越大,从而消耗的内存也会越来越大,如果Activity配置了这个属性就无敌了,它会怎么做呢?如果在已经打开A后打开了B C D E…等等,如果这个时候你需要打开A,但又想销毁B C D E…的时候,此属性就满足需求了,这时候你会发现你内存使用就下降了,因为B C D E…已经被销毁。

        经验谈:当然,并不是说设置了singleTask就通用一切了,前面说过了,每种用法都有其自身道理,singleTask想做到的是,显示当前堆栈中已存在的Activity并不重新创建,而是复用,如果堆栈中已存在需要打开的Activity,那么先将此栈中Activity之上的其它Activity销毁,露出已存在的Activity,并执行它的onNewIntent方法。

      当然,如果当前栈中不存在,那就创建一个新的置于栈顶。

      一句话记忆:只要A存在栈内,那么就将A之上的全部销毁(不包含A),同时显示并复用A,执行onNewIntent方法。否则,创建一个新A置于栈顶。

D.   singleInstance

      singleInstance模式下,会创建一个新的Task栈。

      例如:当前栈的结构为:A BC D。

      在D中通过Intent打开E(E的模式为singleInstance),那么会新建一个Task 栈2,栈Task 1中结构依旧为A B C D,栈2中结构为E,此时屏幕中显示E。

      此类模式,通常会在打开另一个App才会使用。比如:打电话,使用平率高,耗资源的应用。在应用中打开微信、新浪微博等客户端。如下图(7)

                                                       图(7)

5.   Activity栈和Task联系

      Task简单的就是一组以栈的模式聚集在一起的Activity组件集合,类似于一个填充了Activity的容器,最先加入的Activity会处于容器最下面,最后加入的处于容器最上面,而从Task中取出Activity是从最顶端先取出,最后取出的是最开始添加Activity,这就是后进先出(Last In First Out)模式,而Activity在Task中的顺序是可以控制的,在Activity跳转时用到Intent Flag可以设置新建activity的创建方式(这里就涉及到了Intent Flag的使用)。

 

6.    Intent Flags 

       Flags: 表示Intent的标志位,常用于Activity的场景中,它和Activity的启动模式有着密切的联系,简单说,flag的有效组合(通常用“|“组合使用)决定如何打开Activity。

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

(1)——  Intent.FLAG_ACTIVITY_NEW_TASK (默认)

      默认的跳转类型,它会重新创建一个新的Activity。

(2)——  FLAG_ACTIVITY_SINGLE_TOP

      这个FLAG就相当于启动模式中的singletop,请参考singletop说明。

(3)——  FLAG_ACTIVITY_CLEAR_TOP

       这个FLAG启动的Activity会把要启动的Activity之上(包含自身)的Activity全部弹出栈空间。例如:原来栈中的结构是A B C D ,从D中跳转到B,释放顺序为D C B,然后重新创建B置于栈顶,栈中的结构就变为了A B了。(这个方法可以用来关闭多个Activity)

       经验:需要销毁栈中A之前的多个activity,但并不想销毁A,就需要FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_SINGLE_TOP组合使用

(4)——  FLAG_ACTIVITY_CLEAR_TASK

       这个Flag使用的前置条件为:API level 11 以上版本,并且需要与FLAG_ACTIVITY_NEW_TASK一起使用。

此标识,用于释放当前栈中所有的activity,然后再创建新的Activity对象置于栈顶。

       例如栈中原有A B C D,需要从D跳转到B,依次释放D C B A,然后创建B,置于栈顶。 

7.    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名。

       android:taskAffinity只有通过标志位为FLAG_ACTIVITY_NEW_TASK的Intent启动Activity时,该Activity的这个属性才会生效,系统才会将具有相同Task亲和力的Task切换到前台,然后启动该Activity,否则该Activity仍然运行在启动它的Task中。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324682648&siteId=291194637