連載內(nèi)容鎮(zhèn)樓:
Android 面試(一 ):說(shuō)說(shuō) Android 的四種啟動(dòng)模式
Android 面試(二): 如何理解 Activity 的生命周期
Android 面試(三): 用廣播 BroadcastReceiver 更新 UI 界面真的好嗎?
Android 面試(四):Android Service 你真的能應(yīng)答自如了嗎役纹?
Android 面試(五):探索 Android 的 Handler
Android 面試(六):你已經(jīng)用 SharedPrefrence 的 apply() 替換 commit() 了嗎偶摔?
一些閑聊
距離上一篇文章似乎又是很久了,看起來(lái)也沒(méi)有很多反饋促脉,催更就更不用說(shuō)了辰斋。哈哈,放棄了瘸味。
話(huà)說(shuō)最近公司在招聘一批至少 5 年開(kāi)發(fā)經(jīng)驗(yàn)的 Android 開(kāi)發(fā)工程師宫仗,我也是忙開(kāi)了花,激動(dòng)得不行呀旁仿。雖說(shuō)我面試過(guò)的技術(shù)開(kāi)發(fā)至少 50 人以上藕夫,但這還是第一次開(kāi)始面試 Android,此時(shí)猶如大姑娘上轎枯冈,還真是頭一回呀毅贮!
所以非常非常非常用心地準(zhǔn)備了良久,然后滿(mǎn)懷激動(dòng)地開(kāi)始了我的 Android 面試官角色尘奏。
無(wú)奈滩褥,面試后的感覺(jué),均是開(kāi)發(fā)效率聽(tīng)起來(lái)很牛逼炫加,第三方 API 用起來(lái)非常順手瑰煎,但問(wèn)到基礎(chǔ),就拿我面試系列的題去問(wèn)琢感,沒(méi)一個(gè)答得上的丢间,甚至是循循善誘,都沒(méi)法好好回答驹针。
面試場(chǎng)景
Android 開(kāi)發(fā)中對(duì)兩個(gè) Activity 之前傳遞數(shù)據(jù)烘挫,應(yīng)該很熟悉吧?
嗯柬甥,當(dāng)然沒(méi)問(wèn)題饮六。一般采用 Intent.putXXX()
就可以實(shí)現(xiàn)各種輕量級(jí)數(shù)據(jù)的傳遞。
那對(duì)于自定義的 Object 呢苛蒲?
直接使用 Bundle
的 putSerializable()
即可卤橄。需要把對(duì)象實(shí)現(xiàn) Serializable
接口,最后使用 Intent.putExtras(Bundle)
把數(shù)據(jù)放進(jìn) Intent
即可臂外。
除了這種方式窟扑,還有其它方式嗎喇颁?和這種方式有什么區(qū)別呢?
我知道還有 Bundle.putParcelable()
嚎货,不過(guò)我們平時(shí)基本都只用 Serializable
方式橘霎。
為什么不用
Parcelable
方式呢?它們有什么不同呢殖属?
因?yàn)楹?jiǎn)單呀姐叁,Serializable
方式只需要實(shí)現(xiàn)接口一句代碼就好了,Parcelable
我記得有很多代碼洗显。對(duì)于它們的區(qū)別嘛外潜,em......額......嗯.......
正文
上面的場(chǎng)景,實(shí)際上就是在我近期發(fā)生的挠唆。作為一個(gè)簡(jiǎn)歷上 09 年入行的大齡 Android 程序員处窥,我非常肯定他的開(kāi)發(fā)能力和解決問(wèn)題的能力损搬,在這方面肯定甩我很多條街碧库,不過(guò)至少在我問(wèn)的問(wèn)題上讓我有點(diǎn)大跌眼鏡柜与,問(wèn)到自定義 View 的繪制順序巧勤,直接回答不知道。問(wèn)到 LaunchMode弄匕,支支吾吾颅悉,不清楚。實(shí)際上不由得讓我們思考迁匠,到底是怎么了剩瓶,難道現(xiàn)在對(duì)于這么多的程序猿,寫(xiě)出符合需求的代碼就變得這么重要了么城丧?還好延曙,當(dāng)下還有很多堅(jiān)持在一線,努力把基礎(chǔ)帶給大家的大神亡哄,比如枝缔,扔物線朱凱,還有非常非常多的伙伴們蚊惯。
大多數(shù)人可能都知道愿卸,Serializable
和 Parcelable
方式最大的區(qū)別是效率上的差異,而且對(duì)于小數(shù)據(jù)截型,其實(shí)差異并不是很大趴荸,這些差別其實(shí)用戶(hù)層面是并不容易發(fā)現(xiàn)的。但這并不代表著宦焦,我們的開(kāi)發(fā)就可以忽視這幾十毫秒甚至是幾毫秒的差距发钝。
Serializable 和 Parcelable 的區(qū)別
可以肯定的是顿涣,兩者都是支持序列化和反序列化的操作。
兩者最大的區(qū)別在于 存儲(chǔ)媒介的不同酝豪,Serializable
使用 I/O 讀寫(xiě)存儲(chǔ)在硬盤(pán)上园骆,而 Parcelable
是直接 在內(nèi)存中讀寫(xiě)。很明顯寓调,內(nèi)存的讀寫(xiě)速度通常大于 IO 讀寫(xiě)锌唾,所以在 Android 中傳遞數(shù)據(jù)優(yōu)先選擇 Parcelable
。
Serializable
會(huì)使用反射夺英,序列化和反序列化過(guò)程需要大量 I/O 操作晌涕, Parcelable
自已實(shí)現(xiàn)封送和解封(marshalled &unmarshalled)操作不需要用反射,數(shù)據(jù)也存放在 Native 內(nèi)存中痛悯,效率要快很多余黎。
有人直接比較過(guò)兩個(gè)的效率差別
我們可以來(lái)看看分別怎么寫(xiě)?
- Serializable 「簡(jiǎn)單易用」一直都是它的代名詞
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
實(shí)現(xiàn)起來(lái)并不容易惧财,它有成噸的模板代碼,這使得對(duì)象變得難以閱讀和維護(hù)扭仁。但如果你真的想成為一個(gè)優(yōu)秀的 Android 開(kāi)發(fā)工程師垮衷,你可能就得多在 Parcelable
上花點(diǎn)時(shí)間了。實(shí)在想偷懶也沒(méi)事乖坠,因?yàn)橛腥嗽?GitHub 上已經(jīng)上傳了 Android Studio 的插件搀突,幫助你自動(dòng)生成這一堆模板。
地址:https://github.com/mcharmas/android-parcelable-intellij-plugin
在兩個(gè) Activity 之間傳遞對(duì)象還需要注意什么呢熊泵?
對(duì)象的大小仰迁,對(duì)象的大小,對(duì)象的大型绶帧P煨怼!卒蘸!
重要的事情說(shuō)三遍雌隅,一定要注意對(duì)象的大小。Intent
中的 Bundle
是使用 Binder
機(jī)制進(jìn)行數(shù)據(jù)傳送的悬秉。能使用的 Binder 的緩沖區(qū)是有大小限制的(有些手機(jī)是 2 M)澄步,而一個(gè)進(jìn)程默認(rèn)有 16 個(gè) Binder
線程,所以一個(gè)線程能占用的緩沖區(qū)就更小了( 有人以前做過(guò)測(cè)試和泌,大約一個(gè)線程可以占用 128 KB)村缸。所以當(dāng)你看到 The Binder transaction failed because it was too large
這類(lèi) TransactionTooLargeException
異常時(shí),你應(yīng)該知道怎么解決了武氓。
總結(jié)
Parcelable
和 Serializable
都可以實(shí)現(xiàn)序列化并且都可用于 Intent
間的數(shù)據(jù)傳遞梯皿,那我們還是得總結(jié)下它們的使用場(chǎng)景:
Serializable 是 Java 的序列化接口仇箱,使用簡(jiǎn)單但開(kāi)銷(xiāo)很大,序列化和反序列化都需要大量的 I/O 操作东羹;而 Parcelable 是 Android 中的序列化方式剂桥,因此更適合于 Android 平臺(tái)上,它的缺點(diǎn)是使用起來(lái)稍微麻煩點(diǎn)属提,但它的效率很高权逗,這是 Android 推薦的序列化方式,因此我們要首選 Parcelable冤议。但 Serializable 也不是在 Android 上無(wú)用武之地斟薇,下面兩種情況就發(fā)日常適合 Serializable:
1. 需要將對(duì)象序列化到設(shè)備;
2. 對(duì)象序列化后需要網(wǎng)絡(luò)傳輸恕酸。