您的位置:首页 > 移动开发 > Android开发

# Android中的任务和返回栈总结

2016-06-17 16:31 609 查看

Android中的任务和返回栈

任务栈的基础知识:

任务是指在执行特定作业时与用户交互的一系列 Activity。 这些 Activity 按照各自的打开顺序排列在堆栈(即“返回栈”)中。

为什么要用任务栈:

为了记录用户开启了那些activity,记录这些activity开启的先后顺序,google引入任务栈(task stack)概念,帮助维护好的用户体验。

如何查看当前系统的任务栈

手机中 –> 长按home或者多任务键会进到 概览屏幕 的一个界面

命令行中 –> adb shell dumpsys activity

基础点关于 Activiy启动模式

在AndroidMainifest.xml文件里面的activity标签设置启动模,简单实例如下:。

<activity
android:name=".FirstActivity"
android:launchMode="singleTop"
android:label="This is FirstActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>


standard,标准模式,每次都会创建新的Activity覆盖在原Activity上。



singleTop,栈顶复用模式,首先判断栈顶Activity是否是要启动的Activity,如果是则不创建新的Activity而直接引用这个Activity;如果不是则创建新的Activity。



singleTask,栈内复用模式,检测整个Activity栈中是否存在当前需要启动的Activity,如果存在则将该Activity置于栈顶,并销毁其上所有Activity。



singleInstance,单实例模式,创建新的任务栈,且该任务栈仅有一个Activity。



通过TaskAffinity 设置新的任务栈:

taskAffinity,任务相关性。xml中的一个属性,标识了一个Activity所需要的任务栈的名字。默认是包名。如果设置了其他的名字如com.test.task1,那启动它的时候就会新建一个名为com.test.task1的任务栈。

<activity
android:name="com.test.task0.MainActivity"
android:label="@string/app_name"
android:launchMode="standard">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category andorid:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity
andorid:name="com.test.SecondActivity"
android:taskAffinity="com.test.task1"
android:label="@string/app_name"
android:launchMode="singleTask"/>

<activity
andorid:name="com.test.ThirdActivity"
android:taskAffinity="com.test.task1"
android:label="@string/app_name"
android:launchMode="singleTask"/>


如果从MainActivity启动SecondActivity,然后再启动ThirdActivity,那么任务栈如下:

Blockquotes com.test.task0 MainActivity

Blockquotes com.test.task1 SecondActivity ThirdActivity

若再从ThirdActivity启动MainActivity,那么任务栈如下:

com.test.task0 MainActivity

com.test.task1 SecondActivity ThirdActivity MainActivity.

总结:通过设置 TaskAffinity 属性更改任务栈属性。

回退栈和通知

通过通知进入Activity存在的问题

默认情况下,从通知启动一个Activity,按返回键会回到主屏幕。但某些时候有按返回键仍然留在当前应用的需求。从通知打开的某个深层次Activity。在此Acitivity中点回退,若不做处理,将会直接返回到AndroidLaunch界面。这是因为在Notification中的PendingIntent会默认开启新的任务栈。当回退的时候此任务栈没有其他新的Activity,默认在PendingIntent 的Activity是任务栈中唯一的 Activity.

举例: HomeActiy=>Step1Activity=>Step2Acitity

某个通知 默认在PendingIntent 指定了Step2Acitity。通过通知栏进入到Step2Acitity。点回退。正常的顺序为:

Step2Activity=>Step1Acitivity=>HomeActivity但是如果通过通知栏这样进入Step2Activity 点回退 会直接退回到Android 桌面。就是因为 PendingIntent会默认开启新的任务栈

解决方法:

通过TaskStackBuilder设置具体的回退路径:

在 AndroidManifest.xml定义Acitivity从属关系。

Android 4.0.3 及更早版本
<activity
android:name=".ResultActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
Android 4.1 及更高版本
<activity
android:name=".ResultActivity"
android:parentActivityName=".MainActivity">
</activity>


代码中做如下处理
Intent intent = new Intent(MainActivity.this, ResultActivity.class);
TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(this);
taskStackBuilder.addParentStack(ResultActivity.class);
taskStackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = taskStackBuilder.getPendingIntent(1, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setContentIntent(pendingIntent);


这样从Notification进入到指定的ResultActivity中。回退到正常的MainActivity中。

TaskStackBuilder 扩展应用

也可以单独使用TaskStackBuilder,让某个二级Acitivity启动的时候启动它的一级Acitity.

在 AndroidManifest.xml定义Acitivity从属关系。

<activity
android:name="com.example.app.ChildActivity
android:parentActivityName="com.example.app.ParentActivity" >
<!-- 下面这段用来兼容API 16之前的版本 -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.app.MainActivity" />
</activity>


//代码中声明如下
Intent intent = new Intent(this, ChildActivity.class);
TaskStackBuilder.create(this)
.addNextIntentWithParentStack(intent)
.startActivities();


通过启动一个无任何层级关系的Acitity 激活应用(目前Lianlian3.0应用采用此方法)

public class SimpleLaunchAppActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Now finish, which will drop the user in to the activity that was at the top
//  of the task stack
finish();
}
}


原理:若通过Notification打开Acitivity后此Acitivy会位于要启动的App的栈顶。自动finish()后,app恢复到切换到后台之前的状态。SimpleLaunchAppActivity不得设置android:taskAffinity。taskAffinity和默认App的包名一致就不会新建任务栈。若设置了taskAffinity为新的任务栈,点回退后 将会回到android launch页面。

联连wifi的解决方案:

通过启动一个无任何层级关系的TransparentSwitchActivity 激活应用**

目前存在的问题是TransparentSwitchActivity里面会根据参数判断 通过通知进入后还有部分逻辑不太人性化和完善。需要提高用户体验。

关于系统默认的清空返回栈

如何用户将任务切换到后台之后过了很长一段时间,系统会将这个任务中除了最底层的那个Activity之外的其它所有Activity全部清除掉。当用户重新回到这个任务的时候,最底层的那个Activity将得到恢复。这个是系统默认的行为,因为既然过了这么长的一段时间,用户很有可能早就忘记了当时正在做什么,那么重新回到这个任务的时候,基本上应该是要去做点新的事情了。当然,既然说是默认的行为,那就说明我们肯定是有办法来改变的,在Manifest中 元素中设置以下几种属性就可以改变系统这一默认行为:

alwaysRetainTaskState

如果将最底层的那个Activity的这个属性设置为true,那么上面所描述的默认行为就将不会发生,任务中所有的Activity即使过了很长一段时间之后仍然会被继续保留。

clearTaskOnLaunch

如果将最底层的那个Activity的这个属性设置为true,那么只要用户离开了当前任务,再次返回的时候就会将最底层Activity之上的所有其它Activity全部清除掉。简单来讲,就是一种和alwaysRetainTaskState完全相反的工作模式,它保证每次返回任务的时候都会是一种初始化状态,即使用户仅仅离开了很短的一段时间。

finishOnTaskLaunch

这个属性和clearTaskOnLaunch是比较类似的,不过它不是作用于整个任务上的,而是作用于单个Activity上。如果某个Activity将这个属性设置成true,那么用户一旦离开了当前任务,再次返回时这个Activity就会被清除掉。

1:参考:Notification to restore a task rather than a specific activity?

2:参考:启动一个Activity时让指定父页面同时启动并处于它的下方

3:参考: Activity与Activity调用栈
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android Task