#### 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的主要方法

如表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,并且這些通知都是可以打開的。
- 前言
- 第1章 Activity的生命周期和啟動模式
- 1.1 Activity的生命周期全面分析
- 1.1.1 典型情況下的生命周期分析
- 1.1.2 異常情況下的生命周期分析
- 1.2 Activity的啟動模式
- 1.2.1 Activity的LaunchMode
- 1.2.2 Activity的Flags
- 1.3 IntentFilter的匹配規則
- 第2章 IPC機制
- 2.1 Android IPC簡介
- 2.2 Android中的多進程模式
- 2.2.1 開啟多進程模式
- 2.2.2 多進程模式的運行機制
- 2.3 IPC基礎概念介紹
- 2.3.1 Serializable接口
- 2.3.2 Parcelable接口
- 2.3.3 Binder
- 2.4 Android中的IPC方式
- 2.4.1 使用Bundle
- 2.4.2 使用文件共享
- 2.4.3 使用Messenger
- 2.4.4 使用AIDL
- 2.4.5 使用ContentProvider
- 2.4.6 使用Socket
- 2.5 Binder連接池
- 2.6 選用合適的IPC方式
- 第3章 View的事件體系
- 3.1 View基礎知識
- 3.1.1 什么是View
- 3.1.2 View的位置參數
- 3.1.3 MotionEvent和TouchSlop
- 3.1.4 VelocityTracker、GestureDetector和Scroller
- 3.2 View的滑動
- 3.2.1 使用scrollTo/scrollBy
- 3.2.2 使用動畫
- 3.2.3 改變布局參數
- 3.2.4 各種滑動方式的對比
- 3.3 彈性滑動
- 3.3.1 使用Scroller7
- 3.3.2 通過動畫
- 3.3.3 使用延時策略
- 3.4 View的事件分發機制
- 3.4.1 點擊事件的傳遞規則
- 3.4.2 事件分發的源碼解析
- 3.5 View的滑動沖突
- 3.5.1 常見的滑動沖突場景
- 3.5.2 滑動沖突的處理規則
- 3.5.3 滑動沖突的解決方式
- 第4章 View的工作原理
- 4.1 初識ViewRoot和DecorView
- 4.2 理解MeasureSpec
- 4.2.1 MeasureSpec
- 4.2.2 MeasureSpec和LayoutParams的對應關系
- 4.3 View的工作流程
- 4.3.1 measure過程
- 4.3.2 layout過程
- 4.3.3 draw過程
- 4.4 自定義View
- 4.4.1 自定義View的分類
- 4.4.2 自定義View須知
- 4.4.3 自定義View示例
- 4.4.4 自定義View的思想
- 第5章 理解RemoteViews
- 5.1 RemoteViews的應用
- 5.1.1 RemoteViews在通知欄上的應用
- 5.1.2 RemoteViews在桌面小部件上的應用
- 5.1.3 PendingIntent概述
- 5.2 RemoteViews的內部機制
- 5.3 RemoteViews的意義
- 第6章 Android的Drawable
- 6.1 Drawable簡介
- 6.2 Drawable的分類
- 6.2.1 BitmapDrawable2
- 6.2.2 ShapeDrawable
- 6.2.3 LayerDrawable
- 6.2.4 StateListDrawable
- 6.2.5 LevelListDrawable
- 6.2.6 TransitionDrawable
- 6.2.7 InsetDrawable
- 6.2.8 ScaleDrawable
- 6.2.9 ClipDrawable
- 6.3 自定義Drawable
- 第7章 Android動畫深入分析
- 7.1 View動畫
- 7.1.1 View動畫的種類
- 7.1.2 自定義View動畫
- 7.1.3 幀動畫
- 7.2 View動畫的特殊使用場景
- 7.2.1 LayoutAnimation
- 7.2.2 Activity的切換效果
- 7.3 屬性動畫
- 7.3.1 使用屬性動畫
- 7.3.2 理解插值器和估值器 /
- 7.3.3 屬性動畫的監聽器
- 7.3.4 對任意屬性做動畫
- 7.3.5 屬性動畫的工作原理
- 7.4 使用動畫的注意事項
- 第8章 理解Window和WindowManager
- 8.1 Window和WindowManager
- 8.2 Window的內部機制
- 8.2.1 Window的添加過程
- 8.2.2 Window的刪除過程
- 8.2.3 Window的更新過程
- 8.3 Window的創建過程
- 8.3.1 Activity的Window創建過程
- 8.3.2 Dialog的Window創建過程
- 8.3.3 Toast的Window創建過程
- 第9章 四大組件的工作過程
- 9.1 四大組件的運行狀態
- 9.2 Activity的工作過程
- 9.3 Service的工作過程
- 9.3.1 Service的啟動過程
- 9.3.2 Service的綁定過程
- 9.4 BroadcastReceiver的工作過程
- 9.4.1 廣播的注冊過程
- 9.4.2 廣播的發送和接收過程
- 9.5 ContentProvider的工作過程
- 第10章 Android的消息機制
- 10.1 Android的消息機制概述
- 10.2 Android的消息機制分析
- 10.2.1 ThreadLocal的工作原理
- 10.2.2 消息隊列的工作原理
- 10.2.3 Looper的工作原理
- 10.2.4 Handler的工作原理
- 10.3 主線程的消息循環
- 第11章 Android的線程和線程池
- 11.1 主線程和子線程
- 11.2 Android中的線程形態
- 11.2.1 AsyncTask
- 11.2.2 AsyncTask的工作原理
- 11.2.3 HandlerThread
- 11.2.4 IntentService
- 11.3 Android中的線程池
- 11.3.1 ThreadPoolExecutor
- 11.3.2 線程池的分類
- 第12章 Bitmap的加載和Cache
- 12.1 Bitmap的高效加載
- 12.2 Android中的緩存策略
- 12.2.1 LruCache
- 12.2.2 DiskLruCache
- 12.2.3 ImageLoader的實現446
- 12.3 ImageLoader的使用
- 12.3.1 照片墻效果
- 12.3.2 優化列表的卡頓現象
- 第13章 綜合技術
- 13.1 使用CrashHandler來獲取應用的crash信息
- 13.2 使用multidex來解決方法數越界
- 13.3 Android的動態加載技術
- 13.4 反編譯初步
- 13.4.1 使用dex2jar和jd-gui反編譯apk
- 13.4.2 使用apktool對apk進行二次打包
- 第14章 JNI和NDK編程
- 14.1 JNI的開發流程
- 14.2 NDK的開發流程
- 14.3 JNI的數據類型和類型簽名
- 14.4 JNI調用Java方法的流程
- 第15章 Android性能優化
- 15.1 Android的性能優化方法
- 15.1.1 布局優化
- 15.1.2 繪制優化
- 15.1.3 內存泄露優化
- 15.1.4 響應速度優化和ANR日志分析
- 15.1.5 ListView和Bitmap優化
- 15.1.6 線程優化
- 15.1.7 一些性能優化建議
- 15.2 內存泄露分析之MAT工具
- 15.3 提高程序的可維護性