深度解析 PendingIntent 及其与 Intent 的差异

深度解析 PendingIntent 及其与 Intent 的区别

什么是Intent

Intent 在组件间被用于进行信息传递(例如 Activitiy, Service, Broadcast Receiver, Content Provider),从而调用不同的组件以完成我想要完成的事。而这里提到的信息是什么呢:是你想要做的事。举例来说吧:

我想要在KFC点一份外卖,那么当这份信息被发送出去以后,KFC以外的外卖店都不会理我,只有KFC会接受这份信息,并且处理它,最后给我送来我要的外卖。

但如果我发出的信息是:我想要一份外卖,那么这就说明我没有指定是谁送给我(这里默认为谁先处理就谁先获得),所以最先处理了我的需求的外卖店会送来外卖,而外卖是什么并不重要;但例子中我指明了:我要KFC的外卖。所以在例子中我们又可以了解到另一个有关Intent的知识:Intent有准确和不准确之分(explicit/implicit)。

而我们接下来要提到的 PendingIntent 就是 implicit Intent 的一种。

什么是PendingIntent

PendingIntent 是在未来被使用的 Intent,这样说感觉很难懂,举个例子吧:

我想在下班以后立刻去健身。那么在健身之前的这段时间里,我都得乖乖呆在办公室里码代码、看动漫、看博客等等……反正我必须等到下班以后,才能去健身。但是在下班以前,我又必须记得我下班以后要去健身。

而在 Android 中,使用 PendingIntent 能够让你允许其他应用能够使用你开发的应用中的权限,去执行一段你写好的代码,还是上面这个例子吧:

我今天决定下班后立刻去健身(发出下班后去健身的PendingIntent,Intent则是健身),下班前我都在干我自己的事情,直到下班后,PendingIntent 被调用,然后调用了其中的 Intent,使得我去健身了。

PendingIntent 能干什么

从上面的介绍中我们能够知道 PendingIntent 的两个特性:一、能够将自开发应用的权限提供给其他应用使用,并执行自开发应用中的一段代码;二、即使获得 PendingIntent 的应用线程被杀死,PendingIntent 也不会因此受影响,因为 PendingIntent 存在于其他线程中。而当 PendingIntent 的响应条件被满足,就会启动相应的 Intent,执行相应的代码。

根据这两个特性,我们就可以发现 PendingIntent 主要被用于处理**非即时**Intent。

例如:XXX发来了一条短信,我在推送中心看到了它,这个信息我可能会立刻处理,也可能会稍后再处理。如果是Boss发来的重要短信,我就得在推送中心点击这条推送内容(通过Intent打开收件箱),打开收件箱并回复Boss;但如果是传销短信,我就会无视它(不通过Intent打开收件箱),或者是有空再点击这条内容,到收件箱中删除它(过一段时间再通过Intent打开收件箱处理这条短信)。

同理,PendingIntent 还可以被运用于闹钟之中

为什么需要 PendingIntent

其实我们着眼于日常生活就能发现,在许多通信过程中,有些事情是需要立刻被处理,有些则可以暂缓甚至无视。那么哪些事情需要立刻被处理,哪些可以暂缓,哪些可以无视,就需要一套标准,我们需要通过标准来判断事情的优先级。在这里我们谈到的标准,就是 PendingIntent 中携带的信息。

但是这里又有新的问题了,这些事情是永远都不会变的吗?大多数情况下,这些发送过来的事情都有可能会改变:产品汪前一秒让你把Button放在左边,可能下一秒就让你放在右边了;Boss前一秒让你开发一个指纹解锁,可能后一秒又说不用了;今天开晨会领导说以后每天都要写一份工作报告,那么此后你每天肯定都要写了。那么PendingIntent 又是怎么满足这些需求的呢?让我们来看看它的四个 Flag吧:

  • FLAG_CANCEL_CURRENT:用于表示被描述的PendingIntent已经存在了,当前发出的PendingIntent应该在产生新的PendingIntent之前被取消。

例:假如你已经设了一个明天早上7点的闹钟,那么你再设一个明天7点的闹钟肯定是没有意义的,你的设置就不会成功,而是被取消。

  • FLAG_NO_CREATE:用于表示对应的PendingIntent不存在,然后返回null而不是创建一个

  • FLAG_ONE_SHOT:用于表示该PendingIntent只能被使用一次

例:你和女神相约明晚去夜跑,但女神明天早上告诉你她以后要和男友一起跑,只能和你去一次,那么你以后不可能每天晚上还执行一个和女神跑步的Intent吧?

  • FLAG_UPDATE_CURRENT:用于更新已存在的PendingIntent携带的Intent中的信息

例:老婆4点发短信告诉你今晚加班不用你接她下班了,你兴高采烈地约了一帮兄弟去大保健,结果5点30的时候老婆告诉你不加班了,你是不是得告诉你的兄弟们你不能去了呢?