ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
#### 5.1.3 PendingIntent概述 在5.1.2节中,我们多次提到PendingIntent,那么PendingIntent到底是什么东西呢?它和Intent的区别是什么呢?在本节中将介绍PendingIntent的使用方法。 顾名思义,PendingIntent表示一种处于pending状态的意图,而pending状态表示的是一种待定、等待、即将发生的意思,就是说接下来有一个Intent(即意图)将在某个待定的时刻发生。可以看出PendingIntent和Intent的区别在于,PendingIntent是在将来的某个不确定的时刻发生,而Intent是立刻发生。PendingIntent典型的使用场景是给RemoteViews添加单击事件,因为RemoteViews运行在远程进程中,因此RemoteViews不同于普通的View,所以无法直接向View那样通过setOnClickListener方法来设置单击事件。要想给RemoteViews设置单击事件,就必须使用PendingIntent, PendingIntent通过send和cancel方法来发送和取消特定的待定Intent。 PendingIntent支持三种待定意图:启动Activity、启动Service和发送广播,对应着它的三个接口方法,如表5-1所示。 表5-1 PendingIntent的主要方法 ![](https://img.kancloud.cn/1e/6e/1e6ec609ece0649a29b5da5c6c660b66_1354x477.png) 如表5-1所示,getActivity、getService和getBroadcast这三个方法的参数意义都是相同的,第一个和第三个参数比较好理解,这里主要说下第二个参数requestCode和第四个参数flags,其中requestCode表示PendingIntent发送方的请求码,多数情况下设为0即可,另外requestCode会影响到flags的效果。flags常见的类型有:FLAG_ONE_SHOT、FLAG_NO_CREATE、FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT。在说明这四个标记位之前,必须要明白一个概念,那就是PendingIntent的匹配规则,即在什么情况下两个PendingIntent是相同的。 PendingIntent的匹配规则为:如果两个PendingIntent它们内部的Intent相同并且requestCode也相同,那么这两个PendingIntent就是相同的。requestCode相同比较好理解,那么什么情况下Intent相同呢?Intent的匹配规则是:如果两个Intent的ComponentName和intent-filter都相同,那么这两个Intent就是相同的。需要注意的是Extras不参与Intent的匹配过程,只要Intent之间的ComponentName和intent-filter相同,即使它们的Extras不同,那么这两个Intent也是相同的。了解了PendingIntent的匹配规则后,就可以进一步理解flags参数的含义了,如下所示。 * FLAG_ONE_SHOT 当前描述的PendingIntent只能被使用一次,然后它就会被自动cancel,如果后续还有相同的PendingIntent,那么它们的send方法就会调用失败。对于通知栏消息来说,如果采用此标记位,那么同类的通知只能使用一次,后续的通知单击后将无法打开。 * FLAG_NO_CREATE 当前描述的PendingIntent不会主动创建,如果当前PendingIntent之前不存在,那么getActivity、getService和getBroadcast方法会直接返回null,即获取PendingIntent失败。这个标记位很少见,它无法单独使用,因此在日常开发中它并没有太多的使用意义,这里就不再过多介绍了。 * FLAG_CANCEL_CURRENT 当前描述的PendingIntent如果已经存在,那么它们都会被cancel,然后系统会创建一个新的PendingIntent。对于通知栏消息来说,那些被cancel的消息单击后将无法打开。 * FLAG_UPDATE_CURRENT 当前描述的PendingIntent如果已经存在,那么它们都会被更新,即它们的Intent中的Extras会被替换成最新的。 从上面的分析来看还是不太好理解这四个标记位,下面结合通知栏消息再描述一遍。这里分两种情况,如下代码中:manager.notify(1, notification),如果notify的第一个参数id是常量,那么多次调用notify只能弹出一个通知,后续的通知会把前面的通知完全替代掉,而如果每次id都不同,那么多次调用notify会弹出多个通知,下面一一说明。 如果notify方法的id是常量,那么不管PendingIntent是否匹配,后面的通知会直接替换前面的通知,这个很好理解。 如果notify方法的id每次都不同,那么当PendingIntent不匹配时,这里的匹配是指PendingIntent中的Intent相同并且requestCode相同,在这种情况下不管采用何种标记位,这些通知之间不会相互干扰。如果PendingIntent处于匹配状态时,这个时候要分情况讨论:如果采用了FLAG_ONE_SHOT标记位,那么后续通知中的PendingIntent会和第一条通知保持完全一致,包括其中的Extras,单击任何一条通知后,剩下的通知均无法再打开,当所有的通知都被清除后,会再次重复这个过程;如果采用FLAG_CANCEL_CURRENT标记位,那么只有最新的通知可以打开,之前弹出的所有通知均无法打开;如果采用FLAG_UPDATE_CURRENT标记位,那么之前弹出的通知中的PendingIntent会被更新,最终它们和最新的一条通知保持完全一致,包括其中的Extras,并且这些通知都是可以打开的。