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

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上。
    cmd-markdown-logo
  • singleTop,栈顶复用模式,首先判断栈顶Activity是否是要启动的Activity,如果是则不创建新的Activity而直接引用这个Activity;如果不是则创建新的Activity。
    cmd-markdown-logo
  • singleTask,栈内复用模式,检测整个Activity栈中是否存在当前需要启动的Activity,如果存在则将该Activity置于栈顶,并销毁其上所有Activity。
    cmd-markdown-logo
  • singleInstance,单实例模式,创建新的任务栈,且该任务栈仅有一个Activity。
    cmd-markdown-logo

通过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调用栈

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值