关于几个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的情况:
activtyB直接进入调用者的task里
有FLAG_ACTIVITY_NEW_TASK的情况:
activityB在自己的task里
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创建的过程
2.点击跳转按钮,来到BActivity,主activity被BActivity压在了task底部
3.继续点击跳转按钮,和第二步过程一样,CActivity压入task,此时task里有主activiy,BActivity,CActivity,CActivity在最顶端,主Activity在最底部
4.从CActivity进行加了flag的跳转,由图可以看出,首先CActivity进行了onPause,然后BActivity直接销毁后重新进行实例化,之后CActivity被销毁
可以看出CActivity的确被弹出task
5.在BActivity按了后退按钮,退到了是主Activity而不是CActivity,进一步可以说明CActivity已经被弹出task
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再重新实例化
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键退出,再打开软件
通过看控制台的输出,可以明显看到,当从桌面点击程序回到程序,BActivity,CActivity都被销毁,打开程序后显示的界面是主Activity
另外在测试中可以看到FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET在Api21之后已经不推荐使用,建议使用FLAG_ACTIVITY_NEW_DOCUMENT,经测试,效果和FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET一样
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,但依旧没有预期的情况出现,因此认为并没有所说的效果
这是系统叙述的作用,简单讲就是一般写代码不会用到这个flag,通常都是在lauchMode时设置了单例模式的话系统会帮你加上
具体这个flag的作用到现在仍然不太明白,希望有大神来解答一下
7.FLAG_ACTIVITY_REORDER_TO_FRONT
这个flag才是真正拥有和上面 所传言的效果,也就是说,“若 将要跳转到的activity 已经存在task中的话,则会把那个activity放到task顶部,不会重新生成”,测试方法为主->B->C->D->B,在D->B附上该flag,结果输出如下
可以看出,这个和前面提到的一个flag:FLAG_ACTIVITY_CLEAR_TOP作用一样,而在提示里面也告知,当两个flag都存在时,这个flag将会被忽略
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的情况
在前往BActivity的intent添加了flag的情况
可以明显看出,若添加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。
之后我又在这个网页: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的情况
BActivity没有添加了singleTop的情况
第三种模式:singleTask 这个有点特殊,类似于FLAG_ACTIVITY_SINGLE_TOP|FLAG_ACTIVITY_CLEAR_TOP
具体看看结果,操作流程为主->B->C->D->B
B设置了singleTask 属性的情况
B没设置singleTask属性的情况
第四种模式:singleInstance
这个模式有点特殊,它的作用是对设置了改属性的activity,当intent跳转时生成一个新的task放置该activity,而且该task只有且仅有一个activity
具体可以看看输出结果就能理解
操作过程为主->A->B->C->D->B,B按返回键
其中D设置了singleInstance属性,从taskId就可以看出DActivity与其他Activity不在同一个task
而且一旦离开了DActivity(D->B)就无法再返回到DActivity了
(一个屏幕截不全,补上剩下的一句)