intent.setFlags方法中的参数值含义

一. intent.setFlags()方法中的参数值含义:

1.FLAG_ACTIVITY_CLEAR_TOP例如现在的栈情况为:A B C D 。D此时通过intent跳转到B,如果这个intent添加FLAG_ACTIVITY_CLEAR_TOP标记,则栈情况变为:A B。如果没有添加这个标记,则栈情况将会变成:A B C D B。也就是说,如果添加了FLAG_ACTIVITY_CLEAR_TOP标记,并且目标Activity在栈中已经存在,则将会把位于该目标activity之上的activity从栈中弹出销毁。这跟上面把B的Launch mode设置成singleTask类似。简而言之,跳转到的activity若已在栈中存在,则将其上的activity都销掉。

2.FLAG_ACTIVITY_NEW_TASK:例如现在栈1的情况是:A B C。C通过intent跳转到D,并且这个intent添加了FLAG_ACTIVITY_NEW_TASK标记,如果D这个Activity在Manifest.xml中的声明中添加了Task affinity,系统首先会查找有没有和D的Task affinity相同的task栈存在,如果有存在,将D压入那个栈,如果不存在则会新建一个D的affinity的栈将其压入。如果D的Task affinity默认没有设置,则会把其压入栈1,变成:A B C D,这样就和不加FLAG_ACTIVITY_NEW_TASK标记效果是一样的了。注意如果试图从非activity的非正常途径启动一个activity(例见下文“intent.setFlags()方法中参数的用例”),比如从一个service中启动一个activity,则intent比如要添加FLAG_ACTIVITY_NEW_TASK标记(编者按:activity要存在于activity的栈中,而非activity的途径启动activity时必然不存在一个activity的栈,所以要新起一个栈装入启动的activity)。简而言之,跳转到的activity根据情况,可能压在一个新建的栈中。

上面的描述,好像有问题,首先,这种描述把Activity栈和Task这两个概念当作一个。

我的理解:Activity栈就是一个存放Activity的栈,也叫返回栈,这个栈可以存放来自不同Application中的Activity,这种操作方式很常见吧。当然这个栈中还可以存放来自不同Task中的Activity。

我们先说一下Task:Task是为完成某一个目的,执行的一系列Activity,这些Activity可以来自不同的Application。点击Home键,切换到主屏,启动另一个应用,会启动一个新的Task。通过一个Activity启动另一个Activity,被认为是一个Task,比如我们在照相机中浏览照片,其实是启动了图片浏览器应用。通过一个service启动Activity,被认为是另一个目的,也就是另一个Task。所以需要在Intent中加一个FLAG_ACTIVITY_NEW_TASK,不过经过试验,如果被Service启动的Activity没有设置android:taskAffinity属性(注意这个属性值必须是包的形式com.sohutv.tv.DlnaPlay,否则在安装应用的时候报错),被启动的activity所在的TaskID和以前的Activity的TaskID是一样的,如果设置了taskAffinity属性,就会产生一个新的Task

 

一般启动一个应用就会创建一个Task,会把这个应用一系列操作的Activity放到这个Task中,(注意,我的理解,加入在这个应用中启动了另一个应用的Activity,也会把启动的Activity放到这个Task中),那我们如何判读一个应用是否启动了呢?这个没有固定的方法,得根据具体情况订,下面是一个思路:

    public boolean isAppRunning() {
        Context context = mContext;
        if (context == null)
            return false;
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> tasksInfo = manager.getRunningTasks(5);
        
        Log.e("task", "List 中task的数量:" + tasksInfo.size());
        
        for (RunningTaskInfo info : tasksInfo) {
            Log.e("task", "task ID : " + info.id);
            Log.e("task", "topActivity = " + info.topActivity.getClassName() + " baseActivity = " + info.baseActivity.getClassName());
            
            if (info.topActivity.getPackageName().equals(context.getPackageName())
                    && info.baseActivity.getPackageName().equals(context.getPackageName())) {
                return true;
            }
        }
        return false;
    }

有这样一种情况,在一个应用中有多个Activity和一个service,其中有一个activity是通过service启动的,我们知道service启动Activity时,需要FLAG_ACTIVITY_NEW_TASK标签。

如果这个应用启动了,然后在某个时刻通过service启动了相应的activity(如果这个Activity没有设置taskAffinity属性),这个被启动的Activity会放到这个应用的Task中,而不是新的Task中。

如果这个应用关闭,但是service还在,还是可以通过service启动Activity,这个时候,就会创建新的Task,将启动的Activity放到这个Task中。

 

我们有时,需要判断一个应用是否启动,然后根据判断的结果去执行相应的动作,需要注意的是,什么时候去判断应用启动否,也是很重要的。

 

3.FLAG_ACTIVITY_NO_HISTORY:例如现在栈情况为:A B C。C通过intent跳转到D,这个intent添加FLAG_ACTIVITY_NO_HISTORY标志,则此时界面显示D的内容,但是它并不会压入栈中。如果按返回键,返回到C,栈的情况还是:A B C。如果此时D中又跳转到E,栈的情况变为:A B C E,此时按返回键会回到C,因为D根本就没有被压入栈中。简而言之,跳转到的activity不压在栈中。

4.FLAG_ACTIVITY_SINGLE_TOP:和Activity的Launch mode的singleTop类似。如果某个intent添加了这个标志,并且这个intent的目标activity就是栈顶的activity,那么将不会新建一个实例压入栈中。简而言之,目标activity已在栈顶则跳转过去,不在栈顶则在栈顶新建activity。

二.intent.setFlags()方法中参数的用例:

很多人使用startActivity时候,会碰到如下的异常:
Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
都知道,Context中有一个startActivity方法,Activity继承自Context,重载了startActivity方法。如果使用Activity的startActivity方法,不会有任何限制,而如果使用Context的startActivity方法的话,就需要开启一个新的task(编者按:参见一.2.的编者按),遇到上面那个异常的,都是因为使用了Context的startActivity方法。解决办法是:Java代码中加一个flag,即intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)。这样就可以在新的task里面启动这个Activity了。

下面是API中的解释,可以详细读一下。

    /**
     * Launch a new activity.  You will not receive any information about when
     * the activity exits.
     *
     * <p>Note that if this method is being called from outside of an
     * {@link android.app.Activity} Context, then the Intent must include
     * the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag.  This is because,
     * without being started from an existing Activity, there is no existing
     * task in which to place the new activity and thus it needs to be placed
     * in its own separate task.
     *
     * <p>This method throws {@link ActivityNotFoundException}
     * if there was no Activity found to run the given Intent.
     *
     * @param intent The description of the activity to start.
     * @param options Additional options for how the Activity should be started.
     * May be null if there are no options.  See {@link android.app.ActivityOptions}
     * for how to build the Bundle supplied here; there are no supported definitions
     * for building it manually.
     *
     * @throws ActivityNotFoundException
     *
     * @see #startActivity(Intent)
     * @see PackageManager#resolveActivity
     */
    public abstract void startActivity(Intent intent, Bundle options);


 

 

转载地址:http://blog.csdn.net/berber78/article/details/7278408

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值