1. 程式人生 > >Intent傳遞資料重複問題

Intent傳遞資料重複問題

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);

之後,這個意圖一旦產生,就會自動清除棧頂的活動,即是說,上一個被開啟的活動會被終結掉,於是就實現了沒有兩個相同的活動被同時開啟。