Activity launchmode和Intent flag详解

学习安卓,首先就要接触和学习Activity,想必大家在学习activity的过程中一定对activity的launchmode有过困惑。好在网络上关于activity launchmode的博客、解释一大堆,可以方便我们去理解和使用activity launchmode模式,但我强烈建议大家还是要自己动手实践做一些例子,这样才能真正理解activity的launchmode,而且经过实践后你会发现,原来网上的那些解释有很多都是错的、过时的,通过亲自实践得出的结论才是真正被理解的,正确的。

闲话少说,我们来看下官方文档列出的四种Activity的启动模式:


“standard”

系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,而每个实例均可属于不同的task,并且一个task可以拥有多个实例。

“singleTop”

如果当前task的顶部已存在 Activity 的一个实例,则系统会通过调用该实例的 onNewIntent() 方法向其传送 Intent,而不是创建 Activity 的新实例。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例(但前提是位于返回栈顶部的 Activity 并不是 Activity 的现有实例)。

“singleTask”

系统创建新task并实例化将其置于新task底部。但是,如果该 Activity 的一个实例已存在于任何一个单独的任务中,则系统会通过调用现有实例的 onNewIntent() 方法向其传送 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。

“singleInstance”

与 “singleTask” 相同,只是系统不会将任何其他 Activity 启动到包含singleInstance实例的task中。该 Activity 始终是其task唯一仅有的成员。


好了,这些是官方文档的说明,这里我要强调两个概念:任务 task 和 返回栈(任务栈)back stack 。任务是指与用户交互的一系列 Activity的集合, 这些Activity 按照各自的打开顺序排列在一个返回栈中,而返回栈(任务栈)则是一个栈,存储一个或多个任务。这里千万不要搞混,有些朋友认为二者是一个东西,就是一个“任务栈”,例如,在singleTask模式中,会新建一个“任务”,而不是新建一个“任务栈”,这个任务在不在一个新的任务栈里还有待商榷,下文会详细介绍。

standard模式自然不用多说,也没什么争议,只要通过intent进行启动,就会创建一个新Activity实例,即使是在intent Flag设定为FLAG_ACTIVITY_CLEAR_TOP时,也会将原有的activity实例干掉,重新创建一个activity。singleTop也好理解,如果当前task的顶部存在该activity的实例就不会创建新的实例,而是调用activity的onNewIntent方法。
关于singleTask,网上的说法则有很多种,很多说法是当activity不存在任何一个任务中时,采用singleTask方法启动会单独建立一个任务栈,activity放在新任务栈的栈底。这种说法不对的,首先,在activity中有个taskAffinity(任务亲和力)的概念,官方文档对taskAffinity的说法是:除有特殊情况(conceptually 概念上,我不知道咋翻译)有相同taskAffinity的activity属于同一个任务(Activities with the same affinity conceptually belong to the same task)。而taskAffinity的优先级要比singleTask、Intent.FLAG_ACTIVITY_NEW_TASK要高,当两个activity有相同的taskAffinity时,singleTask并不会新建一个任务栈,它只是当该activity不存在于任何一个任务中时,在当前任务栈中新建一个activity,新建立的activity和当前app原有的任务在一个相同的任务栈中,当新建的activity的taskaffinity与之前不同时,才会新建返回栈并将activity放置其中。如果该Activity的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的 onNewIntent() 方法向其传送 Intent。而singleInstance不同,它“无视”taskAffinity,将activity启动到新的任务栈中,并且该 Activity 始终是其任务唯一仅有的成员。这里我们可以做个小例子验证一下:

这里我创建了三个Activity:Activity1 、Activity2、Activity3。Activity1中包含了一个button,会跳转到Activity2,Activity2有两个button,一个跳到Activity1,一个会跳到Activity3。Activity3和Activiyt1一样,只包含了一个button,可以跳转到Activity2。代码和布局如下:
Activity1:

public class Activity1 extends Activity {
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_single_task1);
        Log.v("lzq", "activity 1 onCreate");
        Log.v("lzq", "activity 1 is task root? " + isTaskRoot());
    }

    public void toActivity2(View view) {
        startActivity(new Intent(this, Activity2.class));
    }
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.v("lzq", "activity 1 onNewIntent");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.v("lzq", "activity 1 onResume");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.v("lzq", "activity 1 onDestroy");
    }
}

布局:
activity1

Activity2:

public class Activity2 extends Activity {
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_single_task2);
        Log.v("lzq", "activity 2 onCreate");
        Log.v("lzq", "activity 2 is task root? " + isTaskRoot());
    }

    public void toActivity3(View view) {
        startActivity(new Intent(this, Activity3.class));
    }

    public void toActivity1(View view) {
        startActivity(new Inte
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值