參考
說說PendingIntent的內(nèi)部機(jī)制
Android PendingIntent 的使用
在Android中,我們常常使用PendingIntent來表達(dá)一種“留待日后處理”的意思。從這個(gè)角度來說,PendingIntent可以被理解為一種特殊的異步處理機(jī)制。不過,單就命名而言,PendingIntent其實(shí)具有一定誤導(dǎo)性,因?yàn)樗炔焕^承于Intent,也不包含Intent,它的核心可以粗略地匯總成四個(gè)字——“異步激發(fā)”。
很明顯,這種異步激發(fā)常常是要跨進(jìn)程執(zhí)行的。比如說A進(jìn)程作為發(fā)起端,它可以從系統(tǒng)“獲取”一個(gè)PendingIntent,然后A進(jìn)程可以將PendingIntent對(duì)象通過binder機(jī)制“傳遞”給B進(jìn)程,再由B進(jìn)程在未來某個(gè)合適時(shí)機(jī),“回調(diào)”PendingIntent對(duì)象的send()動(dòng)作,完成激發(fā)。
PendingIntent 是 Android 提供的一種用于外部程序調(diào)起自身程序的能力,生命周期不與主程序相關(guān)。外部程序通過 PendingIntent 只能調(diào)用起三種組件:
- Activity
- Service
- Broadcast
PendingIntent 的使用場(chǎng)景有三個(gè):
- 使用 AlarmManager 設(shè)定鬧鐘
- 在系統(tǒng)狀態(tài)欄顯示 Notification
- 在桌面顯示 Widget
PendingIntent 也只能通過下列的靜態(tài)方法獲取:
// 獲取 Broadcast 關(guān)聯(lián)的 PendingIntent
PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags)
// 獲取 Activity 關(guān)聯(lián)的 PendingIntent
PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)
PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags, Bundle options)
// 獲取 Service 關(guān)聯(lián)的 PendingIntent
PendingIntent.getService(Context context, int requestCode, Intent intent, int flags)
坦白說,這幾個(gè)函數(shù)的命名可真不怎么樣,所以我們簡(jiǎn)單解釋一下。上面的getActivity()的意思其實(shí)是,獲取一個(gè)PendingIntent對(duì)象,而且該對(duì)象日后激發(fā)時(shí)所做的事情是啟動(dòng)一個(gè)新activity。也就是說,當(dāng)它異步激發(fā)時(shí),會(huì)執(zhí)行類似Context.startActivity()那樣的動(dòng)作。相應(yīng)地,getBroadcast()和getService()所獲取的PendingIntent對(duì)象在激發(fā)時(shí),會(huì)分別執(zhí)行類似Context..sendBroadcast()和Context.startService()這樣的動(dòng)作。
PendingIntent 是系統(tǒng)對(duì)于待處理數(shù)據(jù)的一個(gè)引用,稱之為:token;當(dāng)主程序被 Killed 時(shí),token 還是會(huì)繼續(xù)存在的,可以繼續(xù)供其他進(jìn)程使用。如果要取消 PendingIntent,需要調(diào)用PendingIntent 的 cancel 方法。
對(duì)于 PendingIntent 容易誤解的一點(diǎn)是:
如果創(chuàng)建了很多 PendingIntent,只要 extra 中的數(shù)據(jù)不同的話,以為就是兩個(gè)不同的 PendingIntent 這種理解是錯(cuò)誤的!!Extras不參與Intent的匹配過程。
正確區(qū)分不同 PendingIntent 有兩種方法:
- PendingIntent.getXXX(…) 方法中的 requestCode 不同
- 通過 Intent.filterEquals 測(cè)試時(shí)不相等
關(guān)于 PendingIntent.getXXX(…) 方法中第四個(gè)參數(shù) flags,在 PendingIntent 定義了四個(gè)比較常用的 FLAG:
//如果新請(qǐng)求的 PendingIntent 發(fā)現(xiàn)已經(jīng)存在時(shí),取消已存在的,用新的 PendingIntent 替換
int FLAG_CANCEL_CURRENT
//如果新請(qǐng)求的 PendingIntent 發(fā)現(xiàn)已經(jīng)存在時(shí),忽略新請(qǐng)求的,繼續(xù)使用已存在的。日常開發(fā)中很少使用
int FLAG_NO_CREATE
//表示 PendingIntent 只能使用一次,如果已使用過,那么 getXXX(...) 將會(huì)返回 NULL
//也就是說同類的通知只能使用一次,后續(xù)的通知單擊后無法打開。
int FLAG_ONE_SHOT
//如果新請(qǐng)求的 PendingIntent 發(fā)現(xiàn)已經(jīng)存在時(shí), 如果 Intent 有字段改變了,這更新已存在的 PendingIntent
int FLAG_UPDATE_CURRENT