Intent傳遞資料重複問題
阿新 • • 發佈:2018-11-08
Android解決Intent中的資料重複問題
轉載地址:http://www.cnblogs.com/anrainie/articles/2383941.html
最近在研究Android,遇到了一些Notification(通知)的問題: 1、Notification如何傳遞引數 2、Notification如何區別化 3、從Intent(意圖)尋找Activity(活動)說起,Android的Activity棧。 =============================================================== 先從傳送通知開始。 首先,在傳送一個Notification前,我們需要準備好一個NotificationManager 獲得途徑: NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); this為Application或者Activity。 然後,定義好我們的Notification: 1、定義一個Notification具備的三個基本引數icon,title,以及when ? int icon=R.drawable.teller_call_1; long when = System.currentTimeMillis(); Notification notification = new Notification(icon, null, when); 這個定義比較隨意。 2、為notification新增開啟關閉方式: //點選notification之後,該notification自動消失 notification.flags = Notification.FLAG_AUTO_CANCEL; //notification被notify的時候,觸發預設聲音和預設震動 notification.defaults=notification.DEFAULT_SOUND|notification.DEFAULT_VIBRATE; 3、為notification新增一個意圖(Intent): //該意圖用來開啟NotificationList這個新的Activity Intent openintent= new Intent(this, NotificationList.class); //包裝該Intent,只有包裝後的Intent才能被Notification所用,這是因為Notification需要指定一些額外的引數 PendingIntent contentIntent = PendingIntent.getActivity(tradeRoom .getApplicationContext(), 0, openintent, 0); notification.setLatestEventInfo(tradeRoom.getApplicationContext(), title, info, contentIntent); 4、傳送通知 //notifacation_id由自己指定,為每一個Notification對應的唯一標誌 mNotificationManager.notify(notifacation_id, notification); ====================================================== 看到這裡,我們明白了,我們可以為Notification指定它的圖示,標題,時間,提醒方式,點選之後的動作。 延展想一下,我們還能做什麼呢? 1、由於每個Notification的ID是唯一的,所以我們可以刪除某些通知: mNotificationManager.cancel(notifacation_id); 2、同理,通過重複傳送相同ID的Notification,我們還可以更新某些通知: mNotificationManager.notify(notifaction_id,newNotification); 3、由於Notification的包裝內容為Intent,我們就可以方便地為通知被點選的觸發的事件傳值: Intent openintent= new Intent(this, NotificationList.class); openintent.putExtra("isRead", true); openintent.putExtra("name", "CaiYu"); 等等,真的可以傳值麼? 答案是可以,但是,這樣傳值就完蛋了。 現在回到下面的位置來: PendingIntent contentIntent = PendingIntent.getActivity(tradeRoom .getApplicationContext(), 0, openintent, 0); 注意最後一個“0”,0表示什麼?表示什麼都不做,然後下次你傳進來的Intent,如果被發現是同一個Intent,則所有通知都保持為同一個Intent。好吧,事實上,Intent並不是同一個,只是Extra被保留了。 嗯,你應該會期望每個Notification都能幹點不一樣的事情,按上面的方式這樣來,每個具備相同Intent的Notification相互之間,其實是毫無區別的。 好,我們來看下除了0以外Android還有什麼設定: 1、PendingIntent.FLAG_UPDATE_CURRENT Extra會被更新為最後一個傳入的Intent的Extra 2、PendingIntent.FLAG_ONE_SHOT send()只能被執行一次,即是說,假如該通知點選後不消失,那麼再次點選不會發生任何事。 3、PendingIntent.FLAG_NO_CREATE 這個最好別用,不建立。 4、PendingIntent.FLAG_CANCEL_CURRENT 這個,會更新Extra,但還是所有的Intent都保持同一個Extra。 嗯,明顯都不是你想要的。 其實答案根本不在PendingIntent包裝上。 PendingIntent所做的全部事情都只是對同樣的Intent進行處理,關鍵詞,在於“同樣的” 既然每次你開啟的都一個Intent,那區分PendingIntent就沒有意義了 所以,在Intent定義的時候,你還需要區分Intent 推薦方式: openintent.setData(Uri.parse("custom://"+System.currentTimeMillis())); 這樣就實現了Intent的區別化,以後每次傳入的Intent都會具備不同的Extra,當然,PendingIntent需要定義為PendingIntent.FLAG_UPDATE_CURRENT 到這個地方,其實還剩下一個問題,很快你就會發現 每次點選通知,都正確的彈出你要的Activity,但是之前的開啟的Activity依舊存在 方法有二: 1、在Activity的onPause()方法體中增加: finish(); 這樣,在開啟新的Activity的時候,舊的就進入了暫停態,啟動onPause(),然後執行finish(),活動結束 好吧,這是個蠢辦法,請不要使用 2、設定Intent: openintent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 是的,這句就夠了,這裡我得說一下Activity的棧機制: 我們先來看看Intent的結構new Intent(context(),Notification.class); 第一個引數為產生該意圖(Intent)的活動,這個邏輯再清晰不過了,要做的事情得有個發出的主體 第二個引數為該意圖的物件,即是這個意圖是什麼,我們來看看。 呃!??這裡沒有物件…… 是的,我們只有了一個物件的類名,但遠遠不是某個具體的物件,這是反射麼?反射能通過一個類名來找到某個特定的類例項麼? 實現如下: Android有一個棧機制,每個產生的活動在過了產生期後,都會進入這個棧,新的活動壓著舊的活動,每一次尋找類名的時候,都預設提取的是棧頂的活動。這也是為什麼Android能快捷的執行返回操作。 回到原點來,我們為Intent新增: openintent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 之後,這個意圖一旦產生,就會自動清除棧頂的活動,即是說,上一個被開啟的活動會被終結掉,於是就實現了沒有兩個相同的活動被同時開啟。