Android初级开发笔记-- Activity启动模式的学习(2)

1,054 阅读4分钟

在上篇文章中已经介绍了和启动模式相关的基础知识,想了解的小伙伴可以戳下方链接:blog.csdn.net/qq_42171948…

在对activity四种启动模式有所理解之后。这篇文章将会继续解决上篇所留下的问题

1.如何设置不同的任务栈?

2.当activityA以标准模式启动B的时候,B的实例被创建且处于activityA任务栈的顶端,那么这个时候B启动了A(standard)呢?

3.这两种设置方式有什么区别呢?常用的标志位有好几个,组合起来使用又有什么不同的效果呢?

我们知道,默认情况下,所有activity都运行在同一个任务栈中,此栈名为 元素设置的软件包名称。那么如何设置不同的任务栈,很简单,用taskAffinity。

taskAffinity

taskAffinity是一个表明activity想在哪个任务栈的参数。在manifest里面可以进行设置。

   <activity android:name=".MainActivity"
            android:taskAffinity="com.example.administrator.test">
  • 每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。默认是包名。
  • 每个task有affinity属性,等于它的根 Activity的taskAffinity的值。
  • 在不设置其他的前提下,经检验,只有在singleTask,和singleInstance模式中,taskAffinity才会起到应有的作用。 贴上代码: 当两个activity的taskAffinity不一样时: manifest:
 <activity android:name=".MainActivity"
            android:taskAffinity="com.example.administrator.test">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".MainActivity2"
            android:launchMode="singleTask"
            android:taskAffinity="com.example.administrator.test1">
        </activity>

mainactivity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView show = (TextView) findViewById(R.id.tv_show);

        show.setText(this.toString() + "\ntaskId:" + this.getTaskId());
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.e("task", "intent1=" + intent);
    }

    public void jump(View v) {
        Intent intent = new Intent(this,MainActivity2.class);
        startActivity(intent);
    }
}

mainactivity2:

public class MainActivity2 extends AppCompatActivity{
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        TextView show = (TextView) findViewById(R.id.tv_show);

        show.setText(this.toString() + "\ntaskId:" + this.getTaskId());
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.e("task","intent2"+intent);
    }
}

现象是:

1.png
2.png

当两个activity的taskAffinity一样时:

3.png
4.png

由此可以得出结论: 以1启动2来说

  • (1) 当1和2的taskAffinity相同时:当第一次创建2 的实例时,并不会创建新的task,乃是将在1的task中创建2的实例;当1的task已经存在2的实例时,此时启动2,则会检查一下task中是否有2实例,然后将2上的其他实例出栈,将2实例置于栈顶,从而实现了跳转。

  • (2) 当1和2的taskAffinity不同时:当第一次创建2 的实例时,将会创建新的task,在指定的task中创建2的实例;当指定task已经存在2的实例时,此时启动2,则会检查一下task中是否有2实例,然后将2上的其他实例出栈,将2实例置于栈顶,从而实现了跳转。

  • 说了这么多,其实就是很简单的一句话,taskAffinity设置新启动的activity应处于哪个task,一种是在创建它的activity所处栈,一种是新栈,其他的分析就是对singleTask的理解而已。

另外,文档给我们提供了一种会出现:本来在某一个Task中,之后出现了转移的情况。 如果该Activity的allowTaskReparenting属性设置为true,当启动它的任务栈进入后台,一个和它有相同affinity的Task进入前台时,该Activity会进入到该前台的task中。

(以下是翻译) 例子是,如果电子邮件包含网页链接,则点击链接会调出可显示网页的 Activity。 该 Activity 由浏览器应用定义,但作为电子邮件任务的一部分启动。 如果将其父项更改为浏览器任务,它会在浏览器下一次转至前台时显示,当电子邮件任务再次转至前台时则会消失。

我的理解:当一个应用A启动了应用B的某个ActivityC后(C的taskAffinity 为B),如果我们将ActivityC的allowTaskReparenting属性设置为true,当应用B被启动后,系统会发现Activity C所需的任务栈已经存在,ActivityC就会从A的任务栈转移到B的任务栈中。

(以下还是翻译) Activity 的亲和关系由 taskAffinity 属性定义。 任务的亲和关系通过读取其根 Activity 的亲和关系来确定。因此,按照定义,根 Activity 始终位于具有相同亲和关系的任务之中。 由于具有“singleTask”或“singleInstance”启动模式的 Activity 只能位于任务的根,因此更改父项仅限于“standard”和“singleTop”模式。

我的理解: 每个task有affinity属性,等于它的根 Activity的taskAffinity的值。singletask和singleinstance模式下,Atask中只能有一个A实例,且为根,那么就不能重新宿主,要不然的话这个栈就崩了呢~而另外两种的话,因为不是根所以可以在特定情境下自由游荡。(若理解得不对,望小伙伴指正)

写在最后

由于篇幅和时间关系,文章就到此结束,剩下的问题待Android初级开发笔记-- Activity启动模式的学习(3)再进行讨论~

内推信息

  • 我们正在招募小伙伴,有兴趣的小伙伴可以把简历发到 app@talkmoney.cn,备注:来自简书社区
  • 详情可以戳这里--> 广州芦苇信息科技