关于几个flag

1.FLAG_ACTIVITY_NEW_TASK

当进行一个activity跳转,A->B,若跳转的activityB,在系统内无其(activityB)的task(亦即属于该activity的应用栈),则新建一个task;若已经有该activityB的task,则不再新建task;

若无包含该flag,则系统则不创建新task,该activity将放在调用者的task里

下图比较生动的展示了这个过程(参考自开头的博客链接)

无FLAG_ACTIVITY_NEW_TASK的情况:

android activity保持高亮 android activity flag_System

activtyB直接进入调用者的task里

有FLAG_ACTIVITY_NEW_TASK的情况:

activityB在自己的task里

 

android activity保持高亮 android activity flag_home键_02

2.FLAG_ACTIVITY_CLEAR_TOP:此flag表示,当跳转时(activityA->activityB),若发现activityB已经在task里,且activityB不在task顶部,则会吧activityB顶部的activity全部清空,是activity保持在task的最顶部。默认情况下,activityB会重新创建自己(即重走activity的创建生命周期oncreat——>onresume)

我自己写了一个代码试验,内容为主Activity,BActivity以及CActivity,主Activity跳转到BActivity,BActivity跳转到CActivity

其中BActivity跳转到CActivity的intent中添加了该flag

代码如下:

主Activity

public class MainActivity extends Activity {
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        System.out.println("这里是主activity的onCreate");
        button=(Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent intent=new Intent(MainActivity.this,BActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        System.out.println("这里是主activity的onResume");
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        System.out.println("这里是主activity的onPause");
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        System.out.println("这里是主activity的onDestroy");
    }
}


BActivity

public class BActivity extends Activity {
    
    private Button button=null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.b_activity);
        System.out.println("这里是B-onCreat");
        
        button=(Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent intent=new Intent(BActivity.this,CActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        System.out.println("这里是B-onResume");
    }

    @Override
    protected void onNewIntent(Intent intent) {
        // TODO Auto-generated method stub
        super.onNewIntent(intent);
        System.out.println("这里是B-onNewIntent");
    }
    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        System.out.println("这里是B-activity的onPause");
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        System.out.println("这里是B-activity的onDestroy");
    }
}

CActivity

public class CActivity extends Activity{
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.c_activity);
        System.out.println("这里是C-activity的onCreate");
        button=(Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent intent=new Intent(CActivity.this,BActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
                startActivity(intent);
            }
        });
        
    }
    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        System.out.println("这里是C-activity的onResume");
    }
    
    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        System.out.println("这里是C-activity的onPause");
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        System.out.println("这里是C-activity的onDestroy");
    }

}

 

1.初始化主Activity,打印显示该activity创建的过程

android activity保持高亮 android activity flag_System_03

2.点击跳转按钮,来到BActivity,主activity被BActivity压在了task底部

android activity保持高亮 android activity flag_ide_04

3.继续点击跳转按钮,和第二步过程一样,CActivity压入task,此时task里有主activiy,BActivity,CActivity,CActivity在最顶端,主Activity在最底部

android activity保持高亮 android activity flag_System_05

4.从CActivity进行加了flag的跳转,由图可以看出,首先CActivity进行了onPause,然后BActivity直接销毁后重新进行实例化,之后CActivity被销毁

可以看出CActivity的确被弹出task

android activity保持高亮 android activity flag_System_06

5.在BActivity按了后退按钮,退到了是主Activity而不是CActivity,进一步可以说明CActivity已经被弹出task

android activity保持高亮 android activity flag_ide_07

 

3.FLAG_ACTIVITY_SINGLE_TOP:在第2个flag的解释中,默认情况activityB会重新创建自己,但若同时使用了FLAG_ACTIVITY_SINGLE_TOP,则该activityB不会重新传建自己,而是在onNewIntent里面进行重新实例化

这个也做了测试,只需把上面的代码intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);改为
 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);即可

结果如下图,很明显此次CActivity跳转到BActivity时,进行的是onNewIntent方法,而不是销毁BActvity再重新实例化

android activity保持高亮 android activity flag_System_08

4.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET:此flag表示,若intent包含该flag,此intent转向的activityB,一旦该activityB所在的task重置,则该activtyB以及activityB以上的activity会清除掉。而task重置会发生在,当一个应用存放在后台,重新点击应用进入界面,此操作系统将自动携带FLAG_ACTIVITY_RESET_TASK_IF_NEEDED的flag,此时task将会重置。

此flag的效果也进行了测验,通过将主Activity到BActivity的intent附上该flag即可测试

测试过程为打开主Activity,跳转到BActivity,在跳转到CActivity,按home键退出,再打开软件

android activity保持高亮 android activity flag_System_09

通过看控制台的输出,可以明显看到,当从桌面点击程序回到程序,BActivity,CActivity都被销毁,打开程序后显示的界面是主Activity

另外在测试中可以看到FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET在Api21之后已经不推荐使用,建议使用FLAG_ACTIVITY_NEW_DOCUMENT,经测试,效果和FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET一样

android activity保持高亮 android activity flag_ide_10

5.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:这个flag与上一个flag可以互相结合着使用,总共有两种情况起作用:启动activity时,创建新的task;已存在后台的task被重新放到前台上

该flag适用于,当你希望你的应用在打开其他应用的activity后,按home键返回,之后再打开软件看到的依旧是你自己应用的界面,而不是其他应用的界面,避免给用户造成开错软件的错觉,则可以使用此flag,与FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET/FLAG_ACTIVITY_NEW_DOCUMENT搭配使用即可

 

6.FLAG_ACTIVITY_BROUGHT_TO_FRONT

这个flag自己写了个程序测试了下,发现没有所谓的“若 将要跳转到的activity 已经存在task中的话,则会把那个activity放到task顶部,不会重新生成”

说说自己的测试方法,我是在主activity跳转到Bactivity时,在该intent上附上这个flag,然后主->B->C->D->B这样跳转,其他跳转intent无附上任何flag

然后按返回键,结果在Cactivity返回后,出现的仍然后Bactivity,看输出语句,D->B时,B的创建是走onCreat,onResume的方法;

另外我也试过主->B->C->D->B,在D->B附上该flag,但依旧没有预期的情况出现,因此认为并没有所说的效果

android activity保持高亮 android activity flag_home键_11

这是系统叙述的作用,简单讲就是一般写代码不会用到这个flag,通常都是在lauchMode时设置了单例模式的话系统会帮你加上

具体这个flag的作用到现在仍然不太明白,希望有大神来解答一下

 

7.FLAG_ACTIVITY_REORDER_TO_FRONT

这个flag才是真正拥有和上面 所传言的效果,也就是说,“若 将要跳转到的activity 已经存在task中的话,则会把那个activity放到task顶部,不会重新生成”,测试方法为主->B->C->D->B,在D->B附上该flag,结果输出如下

android activity保持高亮 android activity flag_ide_12

可以看出,这个和前面提到的一个flag:FLAG_ACTIVITY_CLEAR_TOP作用一样,而在提示里面也告知,当两个flag都存在时,这个flag将会被忽略

android activity保持高亮 android activity flag_home键_13

 

8.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

对与这个flag,我在网上看到的解释是 “如果调出的Activtivity只是一个功能片段,并没有实际的意义,也没有必要出现在长按Home键调出最近使用过的程序类表中,那么使用FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS”

大概了解他的意思,也就是说通过这个flag,可以使跳转到的activity不显示在长按home键里的列表,但不太理解它的实际作用,于是我继续查了下,发现了这样一个帖子:http://stackoverflow.com/questions/7759556/flag-activity-exclude-from-recents-excludes-whole-application-not-only-the-acti

按我的理解 是他希望通过notification打开的页面不保留在task里面,在长按home键后点击自己的软件时,该activity已经消失,显示的是他的主activity。他添加了该flag后发现,程序会把它的整个应用消掉,导致长按home键显示不了他的应用

我自己试着写了段代码重现他的情况,可是却无法遇到他说的这种情况。

代码如下

public class MainActivity extends Activity {
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        System.out.println("这里是主activity的onCreate");
        
        NotificationManager nm=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        
        Intent i=new Intent(this,BActivity.class);
   //   i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);        i.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);   
        PendingIntent contentIntent=PendingIntent.getActivity(this, 0, i,  PendingIntent.FLAG_UPDATE_CURRENT);
        
        Notification n=new Notification.Builder(this)
        .setContentText("content")
        .setContentTitle("Title")
        .setSmallIcon(R.drawable.ic_launcher)
        .setTicker("show")
        .setContentIntent(contentIntent)
        .build();
        n.flags=Notification.FLAG_AUTO_CANCEL;
        
        nm.notify(0, n);
        }

}无论是否添加Intent.FLAG_ACTIVITY_NEW_TASK,都无法重现他遇到的问题。

我试过点开app,然后按home键回到桌面或者不会到桌面,再点击notification跳到BActivity,在按home键回到主界面,再长按Home键,列表里有我这个测试app

点击进入,则依旧显示的是BActivity

不过在几次测试的时候也发现了这个flag的用处,首先这个flag起作用的情形为:当我点开应用,此时生成notification,然后我退出应用(不是按Home键,而是返回退出),然后点击notification,进入BActivity,接着无论是点击返回退出activity或者按Home键进入桌面,此时再长按Home键会发现该Activity不显示再列表里面

另外,再退出Bactivity时,若是点击退出按钮,再点击应用图标(桌面上),打开的是主Activity,而如果是按Home键返回桌面,再点击应用图标(桌面上的),则进入的是BActivity。这证明了该flag的作用,只是消去显示在长按Home键的历史列表里面,而没有将该activity销毁,在控制台的打印结果也印证了这一说法,点击Home键退出时,BActivity只是onPause,而没有销毁。

9.FLAG_ACTIVITY_FORWARD_RESULT

该flag可以参考这个http://www.2cto.com/kf/201502/376023.html

如果去掉这个flag,则主Activity,也就是链接地址里的ActivityA,则会在onActivityResult拿不到arg2的数据】

10.FLAG_ACTIVITY_NO_ANIMATION 该flag作用很简单,取消掉intent跳转时的动画效果

11.FLAG_ACTIVITY_NO_HISTORY 该flag的作用有点类似于startActivity后添加finish函数有点类似,不过也有点区别

在BActivity添加finish的情况

android activity保持高亮 android activity flag_home键_14

在前往BActivity的intent添加了flag的情况

android activity保持高亮 android activity flag_System_15

可以明显看出,若添加finish的话,当跳转离开该页面(BActivity)时,该activity会在跳转后销毁

而添加flag则不会,他是等到重新点返回按钮回去时,才会将其销毁

12.FLAG_ACTIVITY_NO_USER_ACTIO

这个flag是与Activity的onUserLeaveHint有关

本人测试过,当主Activity跳转到BActivity的intent跳转时,不希望调用主Activity的onUserLeaveHint方法,则在跳转的intent添加该flag即可

13.FLAG_ACTIVITY_PREVIOUS_IS_TOP

关于这个flag我研究了好久,但一直没搞懂它的作用,按官方文档解释,他的意思应该是"若B->C的intent跳转上加上该flag,则C将不作为top,仍旧为B是top。"

然后应该还有C将自我结束掉的意思。我测试过B->C->D,然后从D返回,希望能看到B,但很遗憾仍旧是C。

android activity保持高亮 android activity flag_home键_16

之后我又在这个网页:http://www.4byte.cn/question/942036/why-the-intent-always-use-flag-activity-forward-result-and-flag-activity-previous-is-top.html 看了下,猜测可能需要跨应用才有作用,于是我尝试了A1->B1->C2(第二个应用)->A1,然后从A1返回,结果看到的依旧是C2

后来我在这个网站看到了一些介绍https://justanapplication.wordpress.com/tag/flag_activity_previous_is_top/#NoteOne

通过搜索flag能查到该flag的一些研究介绍,由于英语水平捉急,说实话没完全看懂。但大致意思就是从源码上解释了为什么无法举一个例子表现该flag起作用的情况。在网上也有看到说该flag无法单独起作用,具体要什么情况起作用,希望有大神能帮忙解释。

上述提到的intent设置的flag,有一些可以通过在Manifest.xml对Activity添加属性解决,这个属性为android:launchMode

总共有4种设置

第一种standard,也即默认模式。这种不需设置,你不设置该属性则系统默认为这个模式

第二种singleTop,作用和FLAG_ACTIVITY_SINGLE_TOP类似

具体可以看看结果,操作过程为主Activity->BActivity->BActivity

BActivity添加了singleTop的情况

android activity保持高亮 android activity flag_home键_17

BActivity没有添加了singleTop的情况

android activity保持高亮 android activity flag_ide_18

第三种模式:singleTask 这个有点特殊,类似于FLAG_ACTIVITY_SINGLE_TOP|FLAG_ACTIVITY_CLEAR_TOP

具体看看结果,操作流程为主->B->C->D->B

B设置了singleTask 属性的情况

android activity保持高亮 android activity flag_ide_19

B没设置singleTask属性的情况

android activity保持高亮 android activity flag_System_20

第四种模式:singleInstance

这个模式有点特殊,它的作用是对设置了改属性的activity,当intent跳转时生成一个新的task放置该activity,而且该task只有且仅有一个activity

具体可以看看输出结果就能理解

操作过程为主->A->B->C->D->B,B按返回键

其中D设置了singleInstance属性,从taskId就可以看出DActivity与其他Activity不在同一个task

而且一旦离开了DActivity(D->B)就无法再返回到DActivity了

android activity保持高亮 android activity flag_ide_21

(一个屏幕截不全,补上剩下的一句)

android activity保持高亮 android activity flag_ide_22