1. 程式人生 > >Activity之間傳遞資料的方式及常見問題總結

Activity之間傳遞資料的方式及常見問題總結

Activity之間傳遞資料一般通過以下幾種方式實現:

  1. 通過intent傳遞資料
  2. 通過Application
  3. 使用單例
  4. 靜態成員變數。(可以考慮 WeakReferences)
  5. 持久化(sqlite、share preference、file等)

一、通過intent傳遞資料
(1)直接傳遞,intent.putExtra(key, value)
(2)通過bundle,intent.putExtras(bundle);
PS:
(1)這兩種都要求傳遞的物件必須可序列化(Parcelable、Serializable)
(2)Parcelable實現相對複雜
(3)關於Parcelable和Serializable,官方說法:

Serializable: it's error prone and horribly slow. 
So in general: stay away from Serializable if possible.

也就是說和Parcelable相比,Seriaizable容易出錯並且速度相當慢。是否這樣,可參見下一篇部落格說明。
(4)通過intent傳遞資料是有大小限制滴,超過限制,要麼拋異常,要麼新的Activity啟動失敗,所以還是很嚴重的啊,可參見下一篇部落格說明。

二、Application
這個應該也都接觸過,將資料儲存早全域性Application中,隨整個應用的存在而存在,這樣很多地方都能訪問。具體使用就不多說了。
但是需要注意的是:
當由於某些原因(比如系統記憶體不足),我們的app會被系統強制殺死,此時再次點選進入應用時,系統會直接進入被殺死前的那個介面,製造一種從來沒有被殺死的假象。那麼問題來了,系統強制停止了應用,程序死了,那麼再次啟動時Application自然新的,那裡邊的資料自然木有啦,如果直接使用很可能報空指標或者其他錯誤。
因此還是要考慮好這種情況的:
(1)使用時一定要做好非空判斷
(2)如果資料為空,可以考慮邏輯上讓應用直接返回到最初的activity,比如用 FLAG_ACTIVITY_CLEAR_TASK 或者 BroadcastReceiver 殺掉其他的activity。

三、使用單例
比如一種常見的寫法:

public class DataHolder {
  private String data;
  public String getData() {return data;}
  public void setData(String data) {this.data = data;}
  private static final DataHolder holder = new DataHolder();
  public static DataHolder getInstance() {return holder;}
}

這樣在啟動activity之前:

DataHolder.getInstance().setData(data);

新的activity中獲取資料:

String data = DataHolder.getInstance().getData();

四、靜態Static
這個可以直接在activity中也可以單獨一個數據結構體,就和單例差不多了。
比如:

public class DataHolder {
  private static String data;
  public static String getData() {return data;}
  public static String setData(String data) {this.data = data;}
}

啟動之前設定資料,新的activity獲取資料。

注意:這些情況如果資料很大很多,比如bitmap,處理不當是很容易導致記憶體洩露或者記憶體溢位的。
所以可以考慮使用WeakReferences 將資料包裝起來。
比如:

public class DataHolder {
  Map<String, WeakReference<Object>> data = new HashMap<String, WeakReference<Object>>();
 
  void save(String id, Object object) {
    data.put(id, new WeakReference<Object>(object));
  }
 
  Object retrieve(String id) {
    WeakReference<Object> objectWeakReference = data.get(id);
    return objectWeakReference.get();
  }
}

啟動之前:

DataHolder.getInstance().save(someId, someObject);

新activity中:

DataHolder.getInstance().retrieve(someId);

這裡可能需要通過intent傳遞id,如果資料唯一,id都可以不傳遞的。save() retrieve()中id都固定即可。

五、持久化資料
那就是sqlite、share preference、file等了。
優點:
(1)應用中所有地方都可以訪問
(2)即使應用被強殺也不是問題了
缺點:
(1)操作麻煩
(2)效率低下
(3)io讀寫嘛,其實還是比較容易出錯的


作者:Rflyee
來源:CSDN
原文:https://blog.csdn.net/rflyee/article/details/47431633