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

2023-05-16

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

# Android中的任务和返回栈总结 的相关文章

  • 使用DBFlow,如何加密已经存在的数据库?

    我正在使用 DBFlow 来处理项目中的数据库 并且我想对现有数据库进行加密 我知道我可能必须删除现有的未加密数据库并创建另一个加密数据库 我也知道我可以将 SQLCipher 与 DBFlow 一起使用 如上所述文档 https gith
  • 虚拟回调接口

    在 Eclipse 为您创建的来自 Google 的示例主从流代码中 片段中包含以下内容 private Callbacks mCallbacks sDummyCallbacks public interface Callbacks pub
  • 无法在 Android Studio 中导出签名的 APK

    当我使用keytool list keystore path to keyfile jks并提供我的密码 我可以看到那里的条目 但是当我在尝试使用相同的密码生成签名的 APK 时使用相同的密码时 我收到错误 无法加载密钥库 密钥库被篡改 或
  • 嵌套 XML 布局文件

    android 有没有办法从另一个布局文件引用 xml 布局文件 为了更好地解释 我有一个名为layout1 xml 和layout2 xml 的布局文件 我可以从layout1 xml引用layout2 xml吗 用这个
  • 当我单击“完成”键时,Android OnEditorActionListener() actionId 给出 0

    我创建了一个键盘 当用户输入数字时 它会输入特定的 EditText 但是当用户单击Done关键 它没有去setOnEditorActionListener但它关闭了键盘 这是我的代码 final EditText txtQty new E
  • Play 商店中的应用描述更新

    我想更新应用程序的描述以及 Play 商店上的屏幕截图 但应用程序保持相同 即相同的版本号 我不想发布新应用程序 因为应用程序中没有任何更改 这可能吗 谷歌也会要求更新应用程序吗 您可以更新描述 也可以更改屏幕截图 您的应用程序将保持不变
  • 什么是 Android 测试协调器?

    谷歌最近发布了Android测试支持库1 0 读完后overview https android developers googleblog com 2017 07 android testing support library 10 is
  • 在光标所在行强制关闭!

    嘿 我正在尝试创建一个应用程序来查找存储在 SQlite 数据库中的 GPS 数据 但我面临一个问题 我构建了一个 DbAdapter 类来创建数据库 现在我尝试使用以下函数从另一个类获取所有数据上的光标 public Cursor fet
  • 如何在 60 分钟后删除共享首选项

    我想存储登录数据 但希望在 60 分钟后删除该数据 执行此操作的正确方法是什么 在这 60 分钟内可以关闭 停止 打开应用程序 我不想使用内部数据库 这是我的访问代码SharedPreferences sharedpreferences g
  • 模拟器无法加载

    我正在使用 hello android 教程并通过 eclipse 创建 avd 启动模拟器时不使用图像 它只是显示一个黑色的后屏 中间有 ANDROID 字样 并且在 ANDROID 字样的末尾有一个闪烁的光标 我已按照 T 的步骤安装
  • Android:WebView/BaseInputConnection 中的退格键

    我在 Android 4 2 中遇到软键盘退格问题 我在 WebView CodeMirror 中有一个自定义编辑器 它使用一个空的
  • AndEngine MenuScene - 无法单击按钮

    我有一个关于 android 和 andengine 的小问题 这是我的主菜单的源代码 AbstractScene is extending Scene public class MainMenuScene extends Abstract
  • 如何在Android模拟器中隐藏应用程序图标?

    我有一个应用程序在启动完成后自动启动 但应用程序图标显示在android模拟器中 现在我想向用户隐藏该图标 这样用户就无法知道应用程序已启动 并且他们无法启动该应用程序手动申请 在您的 AndroidManifest xml 文件中 您可能
  • 使用 Proguard 通过 Dropbox.com 库混淆 Android 应用程序

    我刚刚创建了一个需要 Dropbox com API 库的 Android 应用程序 我现在尝试在 发布 模式下构建应用程序 并希望在代码上运行混淆器以对其进行混淆 但是 每当我尝试运行 Proguard 时 都会收到以下错误 Progua
  • 活动加载缓慢

    我的应用程序中有大约 50 个活动 但其中一个活动非常慢 我的意思是当我按下按钮进入该活动时 需要很长时间 有时会出现黑屏 在该活动中 我有一个按钮 如果我单击该按钮 则需要很长时间才能执行 代码很轻 只有一个Button EditText
  • Android 中 Activity 之间的 3D 动画

    How to create animation between two Activity look like As Screen shot in android 搜索jazzyviewpager 这是link https github co
  • Android计算两个日期之间的天数

    我编写了以下代码来查找两个日期之间的天数 startDateValue new Date startDate endDateValue new Date endDate long diff endDateValue getTime star
  • 使 Recyclerview 固定高度并可滚动

    已解决以下检查答案 所以我试图为我的 Android 应用程序创建评论功能 我想在 recyclerview 中显示评论 然后在 recyclerview 下方有一个按钮和文本视图来添加评论 我想让 recyclerview 具有一定的高度
  • onPrepareOptionsMenu 复制 ActionBar 中的项目

    当我使用 onPrepareOptionsMenu 添加菜单项时 该菜单项会在操作栏中复制其自身 我正在使用片段并在主要活动的 ActionBar 中创建初始菜单 如下所示 Override public boolean onCreateO
  • Android ScrollView,检查当前是否滚动

    有没有办法检查标准 ScrollView 当前是否正在滚动 方向是向上还是向下并不重要 我只需要检查它当前是否正在滚动 ScrollView当前形式不提供用于检测滚动事件的回调 有两种解决方法可用 1 Use a ListView并实施On

随机推荐