PendingIntent 是個啥?官方文檔描述的很到位。我給翻譯翻譯

博客原文: [11月的好奇心] PendingIntent 是啥?爲何不少場景不能直接用 Intent 非要用 PendingIntent?bash

出於對 PendingIntent 的好奇心,翻閱了不少資料。最後發現仍是官方文檔描述地到位。前三段話讀下去已經解決了個人大部分疑惑。整篇讀完有種豁然開朗的快感。 等翻譯完,開始有點不解本身最初居然會有爲何不直接使用 Intent 代替 PendingIntent? 這樣的問題。網絡

總之,對於對 PendingIntent 尚有疑問的同窗來講,這文檔是真不錯。app


/**
 * A description of an Intent and target action to perform with it.  Instances
 * of this class are created with {@link #getActivity}, {@link #getActivities},
 * {@link #getBroadcast}, and {@link #getService}; the returned object can be
 * handed to other applications so that they can perform the action you
 * described on your behalf at a later time.
複製代碼

這裏說PendingIntentIntent行爲的描述類。相似於咱們用一個文件句柄,來講明它所對應的文件。 它由這四個方法建立:getActivity getActivities getBroadcast getService。 它能夠被其它應用調用以執行你預先聲明的行爲。less

這裏能夠這麼對比理解: FileDescriptor 用來描述文件 Socket 用來描述網絡 PendingIntent 用來描述行爲ide

若是把類名改成 IntentDescriptor 或許會更好理解。ui


*
 * <p>By giving a PendingIntent to another application,
 * you are granting it the right to perform the operation you have specified
 * as if the other application was yourself (with the same permissions and
 * identity).  As such, you should be careful about how you build the PendingIntent:
 * almost always, for example, the base Intent you supply should have the component
 * name explicitly set to one of your own components, to ensure it is ultimately
 * sent there and nowhere else.
 *
複製代碼

PendingIntent 交給其它應用,你就授予了它們進行其所定義的行爲的權利。 因此你建立 PendingIntent 必定要格外當心:記住在你定義的 Intent 中加上限制用的包名、類名,以確保它只被你但願的對象使用。this

這段是在說,我不只告訴你你該作啥,連權限也給你了。spa

這擱在軍營中,就是一道虎符啊。因此必定要聲明好把虎符具體交到誰的手中,否則會很危險。翻譯


* <p>A PendingIntent itself is simply a reference to a token maintained by
* the system describing the original data used to retrieve it.  This means
* that, even if its owning application's process is killed, the * PendingIntent itself will remain usable from other processes that * have been given it. If the creating application later re-retrieves the * same kind of PendingIntent (same operation, same Intent action, data, * categories, and components, and same flags), it will receive a PendingIntent * representing the same token if that is still valid, and can thus call * {@link #cancel} to remove it. * 複製代碼

咱們如今知道 PendingIntent 其實就是個 IntentDescriptor 行爲描述符,可是它存到哪裏了呢? maintained by the system,和文件同樣,被系統維護。因此不管建立它的進程是否存在,它都和文件同樣,被系統保存在了某個地方。只要你擁有「讀取權限」,就能隨時獲取它。 若是建立 PendingIntent 的程序後來又要獲取相同類型的 PendingIntent(相同的操做、相同的 Intent action、data、categories、component、flags),那麼它會獲取到和以前相同的 token, 前提是它仍然有效。此時你能夠取消它,若是你但願的話。code


* <p>Because of this behavior, it is important to know when two Intents
* are considered to be the same for purposes of retrieving a PendingIntent.
* A common mistake people make is to create multiple PendingIntent objects
* with Intents that only vary in their "extra" contents, expecting to get
* a different PendingIntent each time.  This does <em>not</em> happen.  The
* parts of the Intent that are used for matching are the same ones defined
* by {@link Intent#filterEquals(Intent) Intent.filterEquals}. If you use two
* Intent objects that are equivalent as per
* {@link Intent#filterEquals(Intent) Intent.filterEquals}, then you will get
* the same PendingIntent for both of them.
*
複製代碼

這段說,上面說過使用兩個相同的 Intent 會獲取到同一個 PendingIntent,那麼什麼樣的 Intent 被認爲是相同的呢? 不少人常犯的錯誤是,認爲只改變 Intent#extra 內容就能夠獲取到不一樣的 PendingIntent。 而事實並不是如此。 Intent 是否相同經過 Intent.filterEquals 判斷。見下圖。只有這個方法返回 false, 才能獲得不一樣的 PendingIntent

filterEquals


* <p>There are two typical ways to deal with this.
*
* <p>If you truly need multiple distinct PendingIntent objects active at
* the same time (such as to use as two notifications that are both shown
* at the same time), then you will need to ensure there is something that
* is different about them to associate them with different PendingIntents.
* This may be any of the Intent attributes considered by
* {@link Intent#filterEquals(Intent) Intent.filterEquals}, or different
* request code integers supplied to {@link #getActivity}, {@link #getActivities},
* {@link #getBroadcast}, or {@link #getService}.
*
* <p>If you only need one PendingIntent active at a time for any of the
* Intents you will use, then you can alternatively use the flags
* {@link #FLAG_CANCEL_CURRENT} or {@link #FLAG_UPDATE_CURRENT} to either
* cancel or modify whatever current PendingIntent is associated with the
* Intent you are supplying.
*/
複製代碼

這段就比較囉嗦了,簡單兩句話說明

在某些場景有兩種方法來避免獲取到相同 PendingIntent

  1. 改變 Intent#filterEquals 中做爲判斷一句的某個字段
  2. 獲取 PendingIntent 時使用不一樣的 requestCode

若是你有多個不一樣的 Intent,但你只須要一個活動的 PendingIntent。那麼你須要經過和它綁定的 Intent 來更新或移除它。

相關文章
相關標籤/搜索