Serializable 都這么牛逼了,Parcelable 還要你何用?


一些閑聊

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

nanchen

話說最近公司在招聘一批至少 5 年開發經驗的 Android 開發工程師,我也是忙開了花,激動得不行呀。雖說我面試過的技術開發至少 50 人以上,但這還是第一次開始面試 Android,此時猶如大姑娘上轎,還真是頭一回呀!

所以非常非常非常用心地准備了良久,然后滿懷激動地開始了我的 Android 面試官角色。

無奈,面試后的感覺,均是開發效率聽起來很牛逼,第三方 API 用起來非常順手,但問到基礎,就拿我面試系列的題去問,沒一個答得上的,甚至是循循善誘,都沒法好好回答。

nanchen

面試場景

Android 開發中對兩個 Activity 之前傳遞數據,應該很熟悉吧?

嗯,當然沒問題。一般采用 Intent.putXXX() 就可以實現各種輕量級數據的傳遞。

那對於自定義的 Object 呢?

直接使用 BundleputSerializable() 即可。需要把對象實現 Serializable 接口,最后使用 Intent.putExtras(Bundle) 把數據放進 Intent 即可。

除了這種方式,還有其它方式嗎?和這種方式有什么區別呢?

我知道還有 Bundle.putParcelable() ,不過我們平時基本都只用 Serializable 方式。

為什么不用 Parcelable 方式呢?它們有什么不同呢?

因為簡單呀,Serializable 方式只需要實現接口一句代碼就好了,Parcelable 我記得有很多代碼。對於它們的區別嘛,em......額......嗯.......

正文

上面的場景,實際上就是在我近期發生的。作為一個簡歷上 09 年入行的大齡 Android 程序員,我非常肯定他的開發能力和解決問題的能力,在這方面肯定甩我很多條街,不過至少在我問的問題上讓我有點大跌眼鏡,問到自定義 View 的繪制順序,直接回答不知道。問到 LauchMode,支支吾吾,不清楚。實際上不由得讓我們思考,到底是怎么了,難道現在對於這么多的程序猿,寫出符合需求的代碼就變得這么重要了么?還好,當下還有很多堅持在一線,努力把基礎帶給大家的大神,比如,扔物線朱凱,還有非常非常多的伙伴們。

大多數人可能都知道,SerializableParcelable 方式最大的區別是效率上的差異,而且對於小數據,其實差異並不是很大,這些差別其實用戶層面是並不容易發現的。但這並不代表着,我們的開發就可以忽視這幾十毫秒甚至是幾毫秒的差距。

Serializable 和 Parcelable 的區別

可以肯定的是,兩者都是支持序列化和反序列化的操作。

兩者最大的區別在於 存儲媒介的不同Serializable 使用 I/O 讀寫存儲在硬盤上,而 Parcelable 是直接 在內存中讀寫。很明顯,內存的讀寫速度通常大於 IO 讀寫,所以在 Android 中傳遞數據優先選擇 Parcelable

Serializable 會使用反射,序列化和反序列化過程需要大量 I/O 操作, Parcelable 自已實現封送和解封(marshalled &unmarshalled)操作不需要用反射,數據也存放在 Native 內存中,效率要快很多。

有人直接比較過兩個的效率差別

nanchen

我們可以來看看分別怎么寫?

  • 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 異常時,你應該知道怎么解決了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM