一些閑聊
距離上一篇文章似乎又是很久了,看起來也沒有很多反饋,催更就更不用說了。哈哈,放棄了。

話說最近公司在招聘一批至少 5 年開發經驗的 Android 開發工程師,我也是忙開了花,激動得不行呀。雖說我面試過的技術開發至少 50 人以上,但這還是第一次開始面試 Android,此時猶如大姑娘上轎,還真是頭一回呀!
所以非常非常非常用心地准備了良久,然后滿懷激動地開始了我的 Android 面試官角色。
無奈,面試后的感覺,均是開發效率聽起來很牛逼,第三方 API 用起來非常順手,但問到基礎,就拿我面試系列的題去問,沒一個答得上的,甚至是循循善誘,都沒法好好回答。

面試場景
Android 開發中對兩個 Activity 之前傳遞數據,應該很熟悉吧?
嗯,當然沒問題。一般采用 Intent.putXXX() 就可以實現各種輕量級數據的傳遞。
那對於自定義的 Object 呢?
直接使用 Bundle 的 putSerializable() 即可。需要把對象實現 Serializable 接口,最后使用 Intent.putExtras(Bundle) 把數據放進 Intent 即可。
除了這種方式,還有其它方式嗎?和這種方式有什么區別呢?
我知道還有 Bundle.putParcelable() ,不過我們平時基本都只用 Serializable 方式。
為什么不用
Parcelable方式呢?它們有什么不同呢?
因為簡單呀,Serializable 方式只需要實現接口一句代碼就好了,Parcelable 我記得有很多代碼。對於它們的區別嘛,em......額......嗯.......
正文
上面的場景,實際上就是在我近期發生的。作為一個簡歷上 09 年入行的大齡 Android 程序員,我非常肯定他的開發能力和解決問題的能力,在這方面肯定甩我很多條街,不過至少在我問的問題上讓我有點大跌眼鏡,問到自定義 View 的繪制順序,直接回答不知道。問到 LauchMode,支支吾吾,不清楚。實際上不由得讓我們思考,到底是怎么了,難道現在對於這么多的程序猿,寫出符合需求的代碼就變得這么重要了么?還好,當下還有很多堅持在一線,努力把基礎帶給大家的大神,比如,扔物線朱凱,還有非常非常多的伙伴們。
大多數人可能都知道,Serializable 和 Parcelable 方式最大的區別是效率上的差異,而且對於小數據,其實差異並不是很大,這些差別其實用戶層面是並不容易發現的。但這並不代表着,我們的開發就可以忽視這幾十毫秒甚至是幾毫秒的差距。
Serializable 和 Parcelable 的區別
可以肯定的是,兩者都是支持序列化和反序列化的操作。
兩者最大的區別在於 存儲媒介的不同,Serializable 使用 I/O 讀寫存儲在硬盤上,而 Parcelable 是直接 在內存中讀寫。很明顯,內存的讀寫速度通常大於 IO 讀寫,所以在 Android 中傳遞數據優先選擇 Parcelable。
Serializable 會使用反射,序列化和反序列化過程需要大量 I/O 操作, Parcelable 自已實現封送和解封(marshalled &unmarshalled)操作不需要用反射,數據也存放在 Native 內存中,效率要快很多。
有人直接比較過兩個的效率差別

我們可以來看看分別怎么寫?
- Serializable 「簡單易用」一直都是它的代名詞
public class TestSerializable implements Serializable {
String msg;
List<ItemBean> datas;
public static class ItemBean implements Serializable{
String name;
}
}
- Parcelable 速度至上
public class TestParcelable implements Parcelable {
String msg;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.msg);
}
TestParcelable(String msg) {
this.msg = msg;
}
private TestParcelable(Parcel in) {
this.msg = in.readString();
}
public static final Creator<TestParcelable> CREATOR = new Creator<TestParcelable>() {
@Override
public TestParcelable createFromParcel(Parcel source) {
return new TestParcelable(source);
}
@Override
public TestParcelable[] newArray(int size) {
return new TestParcelable[size];
}
};
}
很明顯,Parcelable 實現起來並不容易,它有成噸的模板代碼,這使得對象變得難以閱讀和維護。但如果你真的想成為一個優秀的 Android 開發工程師,你可能就得多在 Parcelable 上花點時間了。實在想偷懶也沒事,因為有人在 GitHub 上已經上傳了 Android Studio 的插件,幫助你自動生成這一堆模板。
地址:https://github.com/mcharmas/android-parcelable-intellij-plugin
在兩個 Activity 之間傳遞對象還需要注意什么呢?
對象的大小,對象的大小,對象的大小!!!
重要的事情說三遍,一定要注意對象的大小。Intent 中的 Bundle 是使用 Binder 機制進行數據傳送的。能使用的 Binder 的緩沖區是有大小限制的(有些手機是 2 M),而一個進程默認有 16 個 Binder 線程,所以一個線程能占用的緩沖區就更小了( 有人以前做過測試,大約一個線程可以占用 128 KB)。所以當你看到 The Binder transaction failed because it was too large 這類 TransactionTooLargeException 異常時,你應該知道怎么解決了。
