构造PendingIntent时第四个参数flags的设置以及在Notification中的不同作用

PendingIntent第四个参数为int类型的flags,首先看一下官方文档对它的描述:

flags May be FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT, or any of the flags as supported by Intent.fillIn() to control which unspecified parts of the intent that can be supplied when the actual send happens.
可见flags可以有四个取值,分别是FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT。这四种取值每一种都有特定的意义。当然,也可以不使用上述四种常量中的任意一种,即不为PendingIntent指定flags,此时只需要传入一个数字0即可。
例如:
PendingIntent.getActivity(context, requestCode, someIntent, 0);
传入0(第四个参数),就意味着你不打算使用任何一种flag来控制PendingIntent的创建。

接下来看一下四种flags的各自功能:

FLAG_CANCEL_CURRENT:如果要创建的PendingIntent已经存在了,那么在创建新的PendingIntent之前,原先已经存在的PendingIntent中的intent将不能使用

FLAG_NO_CREATE:如果要创建的PendingIntent尚未存在,则不创建新的PendingIntent,直接返回null

FLAG_ONE_SHOT:相同的PendingIntent只能使用一次,且遇到相同的PendingIntent时不会去更新PendingIntent中封装的Intent的extra部分的内容

FLAG_UPDATE_CURRENT:如果要创建的PendingIntent已经存在了,那么在保留原先PendingIntent的同时,将原先PendingIntent封装的Intent中的extra部分替换为现在新创建的PendingIntent的intent中extra的内容

PendingIntent重写了equals方法,判定两个PendingIntent是否相同的依据是它封装的Intent是否“相同”和requestCode是否一致。注意,“相同”上打了引号,这是因为在比较PendingIntent中封装的intent时是否相同时,使用的是Intent的filterEquals方法,该方法认为只要两个intent具有相同的action、data、categories、components、type和flags(这个flags是intent的flags)就认为它们两个是“相同”的,filterEquals是不会比较两个intent的extra部分和内存地址的。另外需要注意的是,Intent并没有重写equals方法,所以如果使用Intent的equals方法比较两个intent对象的话,比较的是两个对象的内存地址。看有如下代码示例:

int requestCode = 1;

Intent intentA = new Intent( );

intentA.putExtra("name","AAA");

Intent intentB = new Intent( );

intentB.putExtra("name","BBB");
PendingIntent p1 = PendingIntent.getActivity(context, requestCode, intentA, 0);
PendingIntent p2 = PendingIntent.getActivity(context, requestCode, intentB, 0);

Log.d("TAG","两个intent是否相等(equals)"+intentA.equals(intentB));//false

Log.d("TAG","两个intent是否相等(filterEquals)"+intentA.filterEquals(intentB));//true

Log.d("TAG","两个PendingIntent是否相等"+p1.equals(p2));//true

有了上面的知识铺垫,接下来,用不同的flags创建Notification中使用的PendingIntent,看看不同的flags所产生的不同效果:

int requestCode = 1;
Intent intentA = new Intent(this, SecondActivity.class);
intentA.putExtra("name","AAA");
Intent intentB = new Intent(this, SecondActivity.class);
intentB.putExtra("name","BBB");
PendingIntent p1 = PendingIntent.getActivity(this, requestCode, intentA, 0);
PendingIntent p2 = PendingIntent.getActivity(this, requestCode, intentB, 0);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification = new Notification.Builder(this).//
		setContentTitle("title").//
		setContentText("Content Text").//
		setSmallIcon(R.drawable.ic_launcher).//
		setAutoCancel(true).//
		setContentIntent(p1).//
		build();
manager.notify(1, notification);
Notification notification2 = new Notification.Builder(this).//
		setContentTitle("title2").//
		setContentText("Content Text2").//
		setSmallIcon(R.drawable.ic_launcher).//
		setAutoCancel(true).//
		setContentIntent(p2).//
		build();
manager.notify(2, notification2);

SecondAcitivity中有一个TextView,用来显示打开SecondActivity的Intent中的String Extra内容:

TextView tv = (TextView) findViewById(R.id.test);
tv.setText(getIntent().getStringExtra("name"));
这里重点看创建PendingIntent时的第四个参数:

使用0时,意味着不使用flags进行创建PendingIntent时的控制,那么此时创建的两个PendingIntent对于安卓来说是一样的,并且不会去更新PendingIntent中封装的intent的extra内容。因此无论点击哪个通知都会跳转到SecondActivity的,并且都会在tv里面显示的是AAA。

现在改变一下创建PendingIntent时的flags:

设置两个PendingIntent的flags均为FLAG_CANCEL_CURRENT,此时随着p2的创建,p1里面的Intent内容会失效。因此,点击第一个Notification的时候,只会自动取消掉该通知(因为设置了AutoCancel为true)并且返回到MainActivity界面而不会发生跳转。当点击第二个Notification的时候,p2发挥作用,所以点击通知会进行跳转到SecondActivity,并在SecondActivity的tv中显示BBB。

设置两个PendingIntent的flags均为FLAG_NO_CREATE,此时无论点击哪个通知,都不会有任何效果,通知即不会自动消失也不会跳转到任何界面(即使MainActivity界面都无法跳转)。这是因为在之前没有“相同”的PendingIntent时,FLAG_NO_CREATE也根本不会创建新的PendingIntent而是直接返回null。这样在点击通知时,根本就没有PendingIntent,所以也不会跳转也不会取消通知。FLAG_CANCEL_CURRENT和FLAG_NO_CREATE最大的区别就是前者会保留PendingIntent,只是把里面的Intent取消掉。另外还可以知道很重要的一点,如果仅仅设置了通知的AutoCancel而没有设置PendingIntent的话,点击通知时,通知是不会消失的!

设置两个PendingIntent的flags均为FLAG_ONE_SHOT,相同的PendingIntent哪个先获得点击,哪个就会被执行。FLAG_ONE_SHOT不具备更新相同的PendingIntent中Intent的extra的能力。因此,如果先点击通知2,会跳转到SecondActivity,并在SecondActivity的tv中显示AAA,再点击通知1,仅仅会取消通知1并返回到MainActivity。如果先点击通知1,会跳转到SecondActivity,并在SecondActivity的tv中显示AAA,再点击通知2,仅仅会取消通知2并返回到MainActivity。

最后,设置两个PendingIntent的flags均为FLAG_UPDATE_CURRENT,使用该flags时,后创建的PendingIntent在遇到已经存在的相同的PendingIntent时,会去更新原先PendingIntent中封装的intent的extra内容为最新的PendingIntent封装的Intent中的extra内容。即,p2会把p1的intent的extra内容更新为自己的extra。此时,无论点击哪个通知,都会跳转到SecondActivity,并且在tv上显示最新一个PendingIntent中Intent中的extra内容,即都会显示BBB。

最后,关于通知使用更详细更全面的介绍,推荐阅读这个人的blog,写的非常全面和详细:

http://blog.csdn.net/vipzjyno1/article/details/25248021

你可能感兴趣的:(构造PendingIntent时第四个参数flags的设置以及在Notification中的不同作用)