activity tasks-and-back-stack

A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the back stack), in the order in which each activity is opened.


task 是与用户交互的activity 的集合,这些activity 是按照打开的顺序保存在栈(back stack)中。


The device Home screen is the starting place for most tasks. When the user touches an icon in the application launcher (or a shortcut on the Home screen), that application's task comes to the foreground. If no task exists for the application (the application has not been used recently), then a new task is created and the "main" activity for that application opens as the root activity in the stack.


可以从手机launcher 启动应用,这样会启动应用task到前台。首次启动时会为应用创建task并将main activity 设置为栈底 root activity 。


 When the current activity starts another, the new activity is pushed on the top of the stack and takes focus. The previous activity remains in the stack, but is stopped. When an activity stops, the system retains the current state of its user interface. When the user presses the Back button, the current activity is popped from the top of the stack (the activity is destroyed) and the previous activity resumes (the previous state of its UI is restored). Activities in the stack are never rearranged, only pushed and popped from the stack—pushed onto the stack when started by the current activity and popped off when the user leaves it using the Back button. As such, the back stack operates as a "last in, first out" object structure. Figure 1 visualizes this behavior with a timeline showing the progress between activities along with the current back stack at each point in time.


当前的activity 启动另外一个activity时,被启动新的activity 就进入启动activity 的stack 顶部,并自己stop。activity stack 不会重新排序,只存在进栈与出栈。当所有的activity 出栈时,task也就不存在了。


按back 键会让activity pop出stack ,按home 键会让task 进入后台,其所在的所以activity 都stopped。


一个activity 可以被实例化多次,甚至在不同的task中实例。


Saving Activity State


As discussed above, the system's default behavior preserves the state of an activity when it is stopped. This way, when users navigate back to a previous activity, its user interface appears the way they left it. However, you can—and should—proactively retain the state of your activities using callback methods, in case the activity is destroyed and must be recreated.

When the system stops one of your activities (such as when a new activity starts or the task moves to the background), the system might destroy that activity completely if it needs to recover system memory. When this happens, information about the activity state is lost. If this happens, the system still knows that the activity has a place in the back stack, but when the activity is brought to the top of the stack the system must recreate it (rather than resume it). In order to avoid losing the user's work, you should proactively retain it by implementing the onSaveInstanceState() callback methods in your activity.

For more information about how to save your activity state, see the Activities document.


正常情况下进入后台 stop 的activity 状态会系统会保持,但是可能为了回收内存被杀掉,当再次回到前台时,其状态就丢失了,但是其中task 的back stack中位置系统会记忆,从而create 这个activity 而不是resume。这样就需要onSaveInstanceState 保存状态。


Managing Tasks


The way Android manages tasks and the back stack, as described above—by placing all activities started in succession in the same task and in a "last in, first out" stack—works great for most applications and you shouldn't have to worry about how your activities are associated with tasks or how they exist in the back stack. However, you might decide that you want to interrupt the normal behavior. Perhaps you want an activity in your application to begin a new task when it is started (instead of being placed within the current task); or, when you start an activity, you want to bring forward an existing instance of it (instead of creating a new instance on top of the back stack); or, you want your back stack to be cleared of all activities except for the root activity when the user leaves the task.

You can do these things and more, with attributes in the <activity> manifest element and with flags in the intent that you pass to startActivity().

安卓应用是通过task 与back stack来管理应用。

1、但有时你需要应用中的一个activity 启动一个新的task而不是在当前task中。

2、启动一个activity时不是在栈顶创建一个新的实例而是将之前的放到顶部。

3、当用户离开task时,清掉除root activity 之外的其它back stack 中activity。


可以通过布局中<activity >配置或者通过startActivity时传入的intent  flag来设置。

In this regard, the principal <activity> attributes you can use are:

And the principal intent flags you can use are:


As such, if Activity A starts Activity B, Activity B can define in its manifest how it should associate with the current task (if at all) and Activity A can also request how Activity B should associate with current task. If both activities define how Activity B should associate with a task, then Activity A's request (as defined in the intent) is honored over Activity B's request (as defined in its manifest).

Note: Some launch modes available for the manifest file are not available as flags for an intent and, likewise, some launch modes available as flags for an intent cannot be defined in the manifest.



"standard" (the default mode)
Default. The system creates a new instance of the activity in the task from which it was started and routes the intent to it. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances.

多个task与back stack  中存在多个实例

"singleTop"
If an instance of the activity already exists at the top of the current task, the system routes the intent to that instance through a call to its  onNewIntent() method, rather than creating a new instance of the activity. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances (but only if the activity at the top of the back stack is  not an existing instance of the activity).

For example, suppose a task's back stack consists of root activity A with activities B, C, and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D. If D has the default "standard" launch mode, a new instance of the class is launched and the stack becomes A-B-C-D-D. However, if D's launch mode is "singleTop", the existing instance of D receives the intent through onNewIntent(), because it's at the top of the stack—the stack remains A-B-C-D. However, if an intent arrives for an activity of type B, then a new instance of B is added to the stack, even if its launch mode is "singleTop".

Note: When a new instance of an activity is created, the user can press the Back button to return to the previous activity. But when an existing instance of an activity handles a new intent, the user cannot press the Back button to return to the state of the activity before the new intent arrived in onNewIntent().


在back stack  top 只允许存在一个实例。即当singleTop 在back stack 顶部时这种情况时,无法再创建其实例,其它情况同standard。


"singleTask"
The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its  onNewIntent() method, rather than creating a new instance. Only one instance of the activity can exist at a time.

Note: Although the activity starts in a new task, the Back button still returns the user to the previous activity.


1、只能存在一个实例,且启动这个activity时会创建其task,因此这类activity 在back stack 中 root 位置。 

2、但这类activity 可以添加其它 activity 到改task。

3、当启动已经存在的这类activity 时,并这类activity 所在task 在后台,这个时候会将改activity所在的task中back stack 中的所以activity 放到启动它的back stack 顶部。按back 键时,按照正常的activity 出栈。

4、当这类activity 在其它应用中配置文件中,这个时候启动这个activity 会拉起其应用创建一个task用于应用。 



"singleInstance".
Same as  "singleTask", except that the system doesn't launch any other activities into the task holding the instance. The activity is always the single and only member of its task; any activities started by this one open in a separate task.

与singleTask 相比,有一下特点

1、这类activity 所在的task只能存在唯一这个activity ,同时这个activity 启动的activity均会重新启动一个task。



Using Intent flags

When starting an activity, you can modify the default association of an activity to its task by including flags in the intent that you deliver to startActivity(). The flags you can use to modify the default behavior are:

FLAG_ACTIVITY_NEW_TASK
Start the activity in a new task. If a task is already running for the activity you are now starting, that task is brought to the foreground with its last state restored and the activity receives the new intent in  onNewIntent().

This produces the same behavior as the "singleTask" launchMode value, discussed in the previous section.

FLAG_ACTIVITY_SINGLE_TOP
If the activity being started is the current activity (at the top of the back stack), then the existing instance receives a call to  onNewIntent(), instead of creating a new instance of the activity.

This produces the same behavior as the "singleTop" launchMode value, discussed in the previous section.

FLAG_ACTIVITY_CLEAR_TOP
If the activity being started is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it are destroyed and this intent is delivered to the resumed instance of the activity (now on top), through  onNewIntent()).

There is no value for the launchMode attribute that produces this behavior.

FLAG_ACTIVITY_CLEAR_TOP is most often used in conjunction with FLAG_ACTIVITY_NEW_TASK. When used together, these flags are a way of locating an existing activity in another task and putting it in a position where it can respond to the intent.

Note: If the launch mode of the designated activity is "standard", it too is removed from the stack and a new instance is launched in its place to handle the incoming intent. That's because a new instance is always created for a new intent when the launch mode is "standard".





http://android.xsoftlab.net/guide/components/tasks-and-back-stack.html



frameworks\base\services\core\java\com\android\server\am\ActivityStarter.java

startActivityLocked(...)   

01-01 00:01:12.278362  1015  1286 I ActivityManager: START u0 {cmp=com.android.settings/.fingerprint.SetupFingerprintEnrollEnrolling (has extras)} from uid 1000 on display 0
01-01 00:01:12.278520  1015  1286 V ActivityManager: Will send result to Token{b408b0a ActivityRecord{70c46ac u0 com.android.settings/.fingerprint.SetupFingerprintEnrollFindSensor t2}} ActivityRecord{70c46ac u0 com.android.settings/.fingerprint.SetupFingerprintEnrollFindSensor t2}
01-01 00:01:12.278601  1015  1286 D ActivityManager: checkComponentPermission: android.permission.START_ANY_ACTIVITY, 5704, 1000, -1, true, 1000, false, false
01-01 00:01:12.297434  1015  1286 V ActivityManager: Starting new activity ActivityRecord{e9d3283 u0 com.android.settings/.fingerprint.SetupFingerprintEnrollEnrolling t2} in existing task TaskRecord{dd92dd2 #2 A=com.google.android.setupwizard.HOME U=0 StackId=0 sz=10} from source ActivityRecord{70c46ac u0 com.android.settings/.fingerprint.SetupFingerprintEnrollFindSensor t2}
01-01 00:01:12.301207  1015  1286 I ActivityManager: Adding activity ActivityRecord{e9d3283 u0 com.android.settings/.fingerprint.SetupFingerprintEnrollEnrolling t2} to stack to task TaskRecord{dd92dd2 #2 A=com.google.android.setupwizard.HOME U=0 StackId=0 sz=10}


01-01 00:01:12.398344  1015  2233 V ActivityManager: ACT-Launching: ActivityRecord{e9d3283 u0 com.android.settings/.fingerprint.SetupFingerprintEnrollEnrolling t2}
01-01 00:01:12.398431  1015  2233 D ActivityManager: Not moving, already top activity: ProcessRecord{6f80473 5704:com.android.settings/1000}
01-01 00:01:12.399667  1015  2233 D ActivityManager: oom: memFactor=0 last=0 allowLow=true numProcs=33 last=33
01-01 00:01:12.400040  1015  2233 D ActivityManager: Did OOM ADJ in 2ms
01-01 00:01:12.400197  1015  2233 V ActivityManager: Launching: ActivityRecord{e9d3283 u0 com.android.settings/.fingerprint.SetupFingerprintEnrollEnrolling t2} icicle=null with results=null newIntents=null andResume=true
01-01 00:01:12.400385  1015  2233 D ActivityManager: ACT-AM_RESTART_ACTIVITY ActivityRecord{e9d3283 u0 com.android.settings/.fingerprint.SetupFingerprintEnrollEnrolling t2} Task:2
01-01 00:00:31.146067   876  1981 V ActivityManager: Moving to RESUMED: ActivityRecord{2eccea8 u0 com.android.settings/.fingerprint.SetupFingerprintEnrollEnrolling t2} (starting new instance) callers=com.android.server.am.ActivityStackSupervisor.realStartActivityLocked:1371 com.android.server.am.ActivityStackSupervisor.startSpecificActivityLocked:1428 com.android.server.am.ActivityStack.resumeTopActivityInnerLocked:2797 com.android.server.am.ActivityStack.resumeTopActivityUncheckedLocked:2253 com.android.server.am.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked:1849 


01-01 00:00:31.174713  4492  4492 V ActivityThread: >>> handling: LAUNCH_ACTIVITY
01-01 00:00:31.175181  4492  4492 D ActivityThread: Handling launch of ActivityRecord{9e56678 token=android.os.BinderProxy@4b56151 {com.android.settings/com.android.settings.fingerprint.SetupFingerprintEnrollEnrolling}} reason=LAUNCH_ACTIVITY startsNotResumed=false
01-01 00:01:12.616904  5704  5704 D ActivityThread: ACT-AM_ON_RESUME_CALLED ActivityRecord{328372a token=android.os.BinderProxy@d6a791b {com.android.settings/com.android.settings.fingerprint.SetupFingerprintEnrollEnrolling}}
01-01 00:01:12.651444  5704  5704 D ActivityThread: LAUNCH_ACTIVITY handled : 0 / ActivityRecord{328372a token=android.os.BinderProxy@d6a791b {com.android.settings/com.android.settings.fingerprint.SetupFingerprintEnrollEnrolling}}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值