是什麼?
在Android中利用Intent在各個元件間通訊。
傳值方法:
- intent.putExtra();
基本型別:
String byte short int long char boolean float double
String[] byte[] short[] int[] long[] char[] boolean[] float[] double[]
序列化:
Parcelable CharSequence Serializable
Parcelable[] CharSequence[]
複製程式碼
-
intent.putCharSequenceArrayListExtra();
-
intent.putIntegerArrayListExtra();
-
intent.putStringArrayListExtra();
-
intent.putParcelableArrayListExtra();
-
intent.putExtras();
傳遞一個bundle物件,所有資料都封裝在bundle中
思考一:Intent最大傳遞資料有限制嗎? 限制是多少?
- 測試案例:用intent傳遞 1M 的byte陣列
Intent intent = new Intent(AActivity.this, BActivity.class);
byte[] bytes = new byte[1024 * 1024];
intent.putExtra("key", bytes);
startActivity(intent);
複製程式碼
- 結果:報異常 TransactionTooLargeException
Caused by: android.os.TransactionTooLargeException: data parcel size 1048956 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:615)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3070)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1518)
複製程式碼
-
結論:說明Intent傳遞資料大小是有限制的;具體限制大小為
((1*1024*1024) - (4096 *2))
思考二:如果有限制,有什麼好的傳輸方案嗎?
-
可採用
EventBus
等類似方案傳遞資料; -
可宣告靜態變數來進行資料傳遞;「效率高,耦合性高」
-
可將資料先持久化再還原,可利用
SharedPreferences
或 存入資料庫
,sp相對簡單;「效率低」
//將物件轉換為 json字串,使用sp儲存
Gson gson = new GsonBuilder().serializeNulls().create();
String json = gson.toJson(userEntity);
//通過json字串取出 ,轉為物件
Gson gson = new GsonBuilder().serializeNulls().create();
UserEntity loginUser = gson.fromJson(jsonEntity,UserEntity.class);
複製程式碼
思考三:Intent 使用 Bundle 儲存資料,到底是值傳遞(深拷貝)還是引用傳遞?
-
Intent傳值型別要求:
1)Intent 傳輸的資料,都存放在一個 Bundle 型別的物件 mExtras 中,Bundle 要求所有儲存的資料,都是可被序列化的。
2)為什麼這裡的
Bundle
要求傳遞的資料必須序列化?因為
Activity
之間傳遞資料,首先要考慮跨程式的問題,而Android中又是通過Binder
機制來解決跨程式通訊的問題。涉及到跨程式,對於複雜資料就要涉及到序列化和反序列化的過程,這就註定是一次值傳遞(深拷貝)的過程。3)所有通過Bundle傳遞資料都需要序列化嗎?
不是,這裡的序列化只與Binder的跨程式通訊有關,其他例如Fragment傳值用到的Bundle不需要序列化。
-
序列化說明:
在 Android 中,序列化資料需要實現
Serializable
或者Parcelable
。對於基礎資料型別的包裝類,本身就是實現了Serializable,而我們自定義的物件,按需實現這兩個序列化介面的其中一個即可。 -
所以這個問題用反證法也可以解釋,如果是引用傳遞,那傳遞過去的只是物件的引用,指向了物件的儲存地址,就只相當於一個Int的大小,也就根本不會出現
TransactionTooLargeException
異常。