原文作者:Z_蕭曉
鏈接:http://www.itdecent.cn/p/b345ed579b99
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
前言
作者:Vasiliy Zukanov,獨立 Android 開發(fā)及軟件顧問
鏈接:https://www.techyourchance.com/the-state-of-native-android-development-november-2019/
譯者:羅昭成,Android 開發(fā)者

當你好不容易學(xué)會了某個框架或者工具,覺得它很好用的時候,它或許就要過時了。
許多 Android 開發(fā)者經(jīng)常會問我,要學(xué)會哪些東西才能成為一個優(yōu)秀的 Android 工程師?對于這個問題,他們的描述或多或少都有些差異。但是,總體來說,我們都需要學(xué)習(xí)一系列的技能,才能成為一個優(yōu)秀的 Android 工程師。
Android 原生開發(fā)的生態(tài)系統(tǒng)變化得非???。至少在過去的五年時間里,我經(jīng)歷過很多 Android 的變化,并且花費大量的時間參與其中。這幾年里,Google 每兩到三年,就會推出一組新的庫和框架作為官方 Android 原生開發(fā)的指導(dǎo)方針。我花了大量的時間,回顧了這幾年的變化,希望從中找出好壞。我相信,有很多的 Android 開發(fā)者,也和我一樣。
過去的一年,大量的內(nèi)容被添加、被廢棄或被刪除,文檔被更改,新的官方指導(dǎo)方針被引入等等。即使我以 Android 原生開發(fā)生態(tài)系統(tǒng)的的標準來看待這些問題,所發(fā)生的這些事情,都是非常瘋狂的。當我開始思考這些內(nèi)容的時候,我已經(jīng)無法在我的腦海中描繪出一個完整的、詳細的 Android 開發(fā)環(huán)境。
因此,我決定要花一些時間去整理這些內(nèi)容,然后再來寫這篇文章。本文中,我會試圖去總結(jié) Android 原生開發(fā)的生態(tài)系統(tǒng)中發(fā)的事情,并且對原生開發(fā)未來的走向做一些預(yù)測。我會將我的想法分成不同的章節(jié)去敘述,這些內(nèi)容沒有特定的順序,但我會把最有爭議的內(nèi)容放在文章最后。
我希望我的這篇文章可以給你帶來一些啟發(fā)和幫助,但是你需要記住,本文不可能包含所有的內(nèi)容,有可能會漏掉許多重要的觀點,并且本文中的內(nèi)容可能會包含我個人的一些偏見。
AndroidX
這個事情說起來有點兒瘋狂,Google 官方在一年半前就發(fā)布了 AndroidX 的預(yù)覽版本。并且在一年前, AndroidX 庫就已經(jīng)很穩(wěn)定了,與此同時,Google 官方也宣布不再對遺留的庫進行支持與開發(fā)。
用“穩(wěn)定”來描述 AndroidX 這個庫有點諷刺,現(xiàn)在關(guān)于 AndroidX 的任何東西都是不穩(wěn)定的。Google 不斷地在 AndroidX 下添加新的庫和框架,使用 androidx 作為命名空間。許多“老”的 API(目前還不到一年)以非??斓乃俣劝l(fā)展。
到目前為止,我已經(jīng)將兩個應(yīng)用程序遷移到了 AndroidX 上了。一切都很順利,我已經(jīng)不記得在這個過程中,帶給了我多少的“驚喜“。Google 也提供了一個工具,Jetifier 可將依賴于支持庫的庫遷移為依賴于等效的 AndroidX 軟件包,一個非常好用的工具。然而,即使是一個很小的工程,也不能實現(xiàn)“一鍵遷移”。
我也參與了沒有遷移 AndroidX 的項目(項目并不計劃遷移到 AndroidX), 現(xiàn)在也沒有任何問題,所以,不遷移 AndroidX, 在有些情況下,也是一種可行的方案。
總而言之,在新的 Android 項目中,建議直接使用 AndroidX。****并且,針對老項目,我也推薦你們將遷移到 AndroidX 列到計劃中,雖然現(xiàn)在你看不到遷移 AndroidX 過后,帶來的任何收益。無論如何,你都有可能在某個時間點進行 AndroidX 的遷移,所以最好能夠按照自己的進度進行遷移,而不是在 6 個月后,你需要使用某個新的 AndroidX 庫時,再進行緊急遷移。
Jetpack
在討論 AndroidX 過后,還必須要提到 Jetpack。在我的印象中,Jetpack 開始是作為“架構(gòu)組件”的一把保護傘推出的。但是到后面,引入了幾乎所有關(guān)于 AndroidX 的 API。因此,現(xiàn)在來看,我們看不到它與 AndroidX 之間的任何區(qū)別,除了 Marketing 和 PR(即市場和公關(guān))。
當你查看 Jetpack 主頁[2]時,會發(fā)現(xiàn),這個頁面并不是一個技術(shù)文檔頁面。這個更像是一個早期的 SaaS 頁面。
看看例子,開發(fā)者“贊譽”:
或者“信賴應(yīng)用”列表:
這些在市場公關(guān)層面更受關(guān)注,如果 Jetpack 在 2020 年申請獨立 IPO,我都不會感到驚訝。
不過,說真的,嘗試向自己生態(tài)系統(tǒng)內(nèi)的開發(fā)者“銷售”API 的想法,我覺得存在一些問題,比如說,誰會想看搜索出來第一個就是 ViewModel 廣告呢?
總而言之,Jetpack 只是 AndroidX 庫的一個聚合,所以在前面寫到的 AndroidX 的內(nèi)容,在很大的程度上也適用于 Jetpack。在后面的內(nèi)容中,我將單獨討論其中一些 API。
后臺作業(yè)
在 Android 應(yīng)用程序不在前臺執(zhí)行邏輯時,你可以有很多種方式來實現(xiàn)后臺運行,這也是 Android 動態(tài)化的用例之一。如果你不引入 doze , SyncAdapter , CGMNetworkManager , FirebaseJobDispatcher , JobScheuler 和最近的 WorkManager,可以使用常規(guī)的啟動服務(wù)(非綁定服務(wù))來實現(xiàn)。這些都是 Google 提供的 API , 我可以說出所有的使用方式。當然,還有一些第三方庫可以使用, 例如:Android-Job。
不過,Google 最近宣布,他們將圍繞 WorkManager 來統(tǒng)一后臺任務(wù)調(diào)度[3]。這聽起來非常棒,我再也不用學(xué)習(xí)那么多后臺調(diào)度的知識了,只是,不知道為什么,我好像以前在哪兒聽到過這句話……
我們不管將來是否會統(tǒng)一使用 WorkManager,WorkManager 都還存在一些問題,比如可靠性。我不想在本文中解釋為什么,但是請你一定要記住,如果你想在應(yīng)用程序中使用 WorkManager,實現(xiàn)后臺作業(yè),一定要去讀一下 dontkillmyapp.com 上的所有內(nèi)容,并且要關(guān)注一下與 WorkManager 相關(guān)的 Google 問題列表[4]。
Android 的后臺作業(yè)由于碎片化等原因,導(dǎo)致它們一團糟,而且還很不可靠。
在過去,我一直主張盡可能對數(shù)據(jù)和其它類型的后臺處理進行同步。我或許是 SyncAdapter 最后的粉絲。今天,考慮到可靠性的問題,我建議,盡可能避免后臺作業(yè)。如果你的老板一直堅持要使用這個功能,請將上面的鏈接發(fā)給他們,告訴他們,后臺作業(yè)可能會需要數(shù)百小時的工作,才能實現(xiàn),并且它帶來的問題也會比它帶來的好處多很多。
很多情況下,后臺作業(yè)的需求是不可避免的。但是在大多數(shù)情況下,你都可以不使用它。雖然有時候會給用戶帶來一些不便,但是這可能是到目前為止的最佳方案。
數(shù)據(jù)庫
在有關(guān) SQLite ORMs 的內(nèi)容里面,沒有什么令人吃驚的內(nèi)容—— Room 主宰著一切。Room 從 2.2.0 開始,添加增量注解解析支持。不過,請你一定要記住,你應(yīng)用程序的架構(gòu)不應(yīng)該關(guān)心你使用的是什么樣的 ORM 框架。說到 Room,“架構(gòu)組件”也只是一個營銷術(shù)語,并不是一個技術(shù)角色。
在 Android ORM 框架中,與 Room 競爭的主要是 SQLDelight。這是一個比 Room 老很多的庫。但是據(jù)我所知,在過去的一年里,它幾乎被全部重寫。****但新版本的 SQLDelight 只針對 Kotlin。****另一方面,SQLDelight 也支持 Kotlin Multiplatform,所以,隨著 Kotlin 使用的增多,我預(yù)計, SQLDelight 的采用率也會隨之增加。
順便說一下,在 AndroidX 的命名空間下,也有 SQLite 的鏡像。我不知道這個會有什么用處,但是如果你在應(yīng)用程序中直接使用 SQLite,也可以對這個進行深入的研究。
此外,我們也不要忘記非關(guān)系型數(shù)據(jù)庫,比如 Realm、Parse、Firebase、ObjectBox 等等 (其中一些,核心還是使用的 SQLite 來實現(xiàn)的),如果我沒有記錯的話,這些非關(guān)系型數(shù)據(jù)庫中,大多數(shù)(甚至全部)都具有自動數(shù)據(jù)同步的功能。在之前有段時間里,它們非常地流行。但是現(xiàn)在,據(jù)我所知,已經(jīng)不再流行了。也就是說,在短期內(nèi),我會持續(xù)關(guān)注非關(guān)系型數(shù)據(jù)庫。
去年,我寫了一個非常復(fù)雜的應(yīng)用程序,對接了一個 Parse 的服務(wù)。這個 App 具有完全的離線支持,服務(wù)端本地化,用戶指定的系統(tǒng)和語言設(shè)定,復(fù)雜的多媒體系統(tǒng)等功能。我在 Android 端上使用了 Parse 的 SDK。除了一些小的 WTF 以外,其他體驗都非常棒。如果你們公司有很多后臺開發(fā)人員,或者說你需要實現(xiàn)大量的服務(wù)端邏輯,這也許并不是最佳解決方案。但是對于僅僅只需要執(zhí)行簡單的 CRUD 操作的初創(chuàng)公司,這或許是一個不錯的選擇。
一個警告:如果你打算采用數(shù)據(jù)庫即服務(wù)解決方案(如 Firebase),請你一定要關(guān)注長期使用的成本和影響。
外部存儲
Android 外部存儲發(fā)生了一個“很有意思”的變動。
如果,你在開發(fā) App 的時候,把 Target API 調(diào)整為 29 及以上,之前獲取 SD 卡文件的方法,現(xiàn)在都不能使用了,并且不會提示任何異?!,F(xiàn)在,你需要使用 Android 存儲訪問框架來進行更細粒度的文件訪問。不幸的是,Android 存儲訪問框架的工作原理與之前的讀取方式完全不同,你可能需要對代碼進行大量的重構(gòu),來實現(xiàn)新的文件訪問和讀取。
Google 原本希望在 Android 10 上,對所有的應(yīng)用程序進行文件訪問的限制,推廣使用 Android 存儲訪問框架的方式進行文件訪問。但是這個改動引起了社區(qū)內(nèi)的強烈抗議,所以 Google 決定推遲推出這個功能。因此,現(xiàn)在即使你的應(yīng)用程序在 Target API 29 及以上,也可以設(shè)置為在“Legacy”模式下可讀取文件。不過,有可能在 Android 的下一個版本,不管你設(shè)置的 Target API 為多少,都會限制應(yīng)用程序使用新的作用域訪問模式。
到目前為止,我也還沒有更新我應(yīng)用程序的文件訪問方式。但是從互聯(lián)網(wǎng)上的討論來看,實現(xiàn)新的文件訪問方式是一項很具挑戰(zhàn)的任務(wù),雖然你的應(yīng)用程序在“Legacy”模式下,沒有任何異常,但是我建議你最好從現(xiàn)在開始,著手對代碼進行重構(gòu)和測試,以防發(fā)生不可控的事情。
Shared Preferences
在幾周前,AndroidX 家族增加了一個新的庫,這條提交信息寫道:
新的庫用來替換 SharedPreferences,新庫的名稱還沒有確定下來,這次提交只是為了評審和設(shè)計文檔(請自行申請設(shè)計文檔)。
現(xiàn)在還沒有什么值得擔心的。不過,從長遠來看,SharedPreferences 會被廢棄掉,取而代之,使用新的庫來實現(xiàn)類似的功能。
與 SharedPreferences 不同的是,這個新的庫默認情況下使用的是異步的方式。換句話說,如果你需要取某個值,你需要實現(xiàn)回調(diào),通過這個回調(diào)才能拿到值。
如果你對這種異步回調(diào)的原理感興趣,你可以去看看 StackOverflow 上的這個回答。Reddit 的一個用戶 Tolriq 分享了他們的 App 遇到的一個 SharedPreferences 的 Bug,這個問題影響了萬分之一的月活用戶。對于一般的應(yīng)用程序來說,這個問題并沒有什么明顯的影響。但在一些需要高可靠性的應(yīng)用上,就顯得很不可靠了。舉個例子,如果在 Android 汽車上,應(yīng)用程序的無響應(yīng)和崩潰會引起駕駛員的注意力被分散,這將有可能導(dǎo)致出現(xiàn)交通意外。
依賴注入
在依賴注入領(lǐng)域,最大的新聞莫過于 Dagger-Android 被棄用,有兩點需要強調(diào)一下,首先我所說的棄用,不是正式的棄用,因為官方并沒有發(fā)布聲明。其次,Dagger-Android 并不是指整個 Dagger 2 框架,只是指其中相對比較新的部分。詳細細節(jié)可以看我的另一篇文章[8]。
在 Android 領(lǐng)域也存在其他的依賴注入框架,但是我不認為他們會比 Dagger 更好。值得一提的是,Koin 是一個不錯的依賴注入框架,但是我依然覺得它也不會引起多大的潮流。它之所以會被采用,無非是這兩個原因,一個是,它擁有比 Dagger 好很多的文檔,降低了很大的學(xué)習(xí)成本。第二個是它基于 Kotlin 進行編寫,因為 Kotlin 的熱度,給它也帶來了不少的關(guān)注。到目前為止,Kotlin 的熱潮幾乎已經(jīng)全部過去了,所以,我預(yù)測,Koin 的關(guān)注也將會逐漸減少。
不管這些框架如何發(fā)展,手動依賴注入的發(fā)展都會很緩慢。
Google 聲稱:隨著應(yīng)用程序的增大,手動依賴注入的成本會出現(xiàn)指數(shù)級增長。但是我并不這么認為,我覺得 Google 既不了解 "指數(shù)" 的含義,也沒有實際去“衡量”過任何東西。這個申明的內(nèi)容是錯誤的,我希望 Google 不再使用這種方式誤導(dǎo)社區(qū)。
事實上,這種手動依賴注入在后端比較常見(尤其是微服務(wù)中,你并不想在每個服務(wù)中都添加對注入框架的依賴),也可以正常的工作。在后端,反射被經(jīng)常用到,所以后端的依賴注入框架并不需要解析編譯時的代碼。
在 Android 上,解決方案與后端有一些不同,我們幾乎不會用反射方案的依賴注入框架,所以就只剩下 Dagger 可以用了。其實,反射雖然會影響性能,但是在大多數(shù)項目,都是可以用的。我的意思并不是建議你們使用反射方案的依賴注入框架,這個選擇并非是非黑即白的,你需要按照你的要求來進行選擇。
無論如何,Android 領(lǐng)域上, Dagger 作為依賴注入框架的現(xiàn)行標準,我們所有人都在使用它。盡管 Google 在宣傳上,對 Dagger 的使用成本使用漂亮的綠色圖形進行展示,但是 Dagger 使用成本在實際上依然會隨著時間增長而快速增長。越來越多的代碼,在編譯構(gòu)建的時候需要花費更多的時間;你的開發(fā)人員越多,代碼編譯的次數(shù)就越多。當然,所有的開發(fā)人員都需要學(xué)習(xí)如何使用 Dagger , 這本身就是一項很大的成本。
換句話說,雖然 Dagger 可以減少項目中編寫的代碼,但是需要花更多的時間去培訓(xùn)新人,在編譯上花費更多的時候。****所以,對大型項目來說,使用 Dagger 會更耗時。
在一個大型項目中,編譯耗時會逐漸成為生產(chǎn)力的瓶頸。當然, Dagger 也提供了很多優(yōu)秀新的功能來幫助你優(yōu)化編譯時間,但前提是,你需要知道如何使用這些工具。讀到這里,我相信你對手動依賴注入會很感興趣。
數(shù)據(jù)綁定
作為一個 Android 開發(fā)者,都知道在寫布局的時候,會經(jīng)常調(diào)用 findViewById() 這個方法。DataBinding 誕生就是為了取代掉這個模板方法。老實說,在使用 findViewById 的時候,我并沒有遇到過任何問題,雖然希望擺脫掉它,但我并不認為使用 DataBinding 就是一個更合理的方式。有一個好消息,很快我們就可以使用 ViewBinding 來擺脫 findViewById 了,也不需要使用 DataBinding。
說句實話,我不相信 DataBinding。對于它想解決的問題來說,這種方案在過于復(fù)雜。在使用 DataBinding 的時候,需要把代碼邏輯放到 XML 布局中,這聽起來很不錯,但是經(jīng)驗豐富的開發(fā)人員都不會這么做,這個做法也是 Databinding 的另一個缺點。
早在 2016 年 11 月的時候,那個時候 Google 還在大肆宣傳 DataBinding。我在 StackOverflow 的回答中作了如下預(yù)測:
我可以非常自信地預(yù)測:DataBinding 不會成為行業(yè)標準。DataBinding 可以帶來短期收益,但是從長遠來看,它將會使代碼變得不可維護。一旦 Databinding 被長期使用,它的缺點就會暴露出來,將來它一定會被廢棄掉。
我沒有統(tǒng)計過使用 DataBinding 的項目,但是很明顯,它沒有成為行業(yè)標準。我從來沒有在自己的項目中使用過它,也很少看到其他開發(fā)者使用。據(jù)我猜測,當 ViewBinding 逐漸成熟,并且被廣泛采用,DataBinding 將會作為一個“傳統(tǒng)”框架,大量地被引用到。
狀態(tài)保存
自從引入 ViewModel 架構(gòu)組件以來,在 Android 應(yīng)用程序中,當配置發(fā)生更改,保存與恢復(fù)狀態(tài)的邏輯,就變成了一個爛攤子,沒有人去管理。雖然這樣子說有點過分,但是我覺得,這已經(jīng)是我最溫和的表達方式了。
Gabor Varadi(又叫 Zhuinden)在 Reddit 論壇中描述了 ViewModel 引入帶來的問題,我不需要再去寫一遍了。再次強調(diào),不推薦使用 onRetainCustomNonConfigurationInstance(),推薦使用 ViewModel。
在帖子的末尾,Gabor 作了一些預(yù)測:
你知道嗎?Fragment 狀態(tài)保存的方法已經(jīng)被棄用了。
在我看來,廢棄 Fragment 狀態(tài)保存的方法是非常好的主意,眾所周知, Fragment 的 onAttach() 和 onDetach() 方法就是為了支持狀態(tài)保存的,現(xiàn)在廢棄了狀態(tài)保存的方法,那這兩個方法也可以被廢棄掉,并且這樣子可以簡化 Fragment 的生命周期。我長期以來都建議不保存 Fragments 的狀態(tài),忽略掉 onAttach 和 onDetach 方法,和我之前寫的處理 Framgent 生命周期方法一致[12]。
盡管有很多理由表明,要廢棄掉 Fragment 的狀態(tài)保存,但是也不可能廢棄掉 onRetainCustomNonConfigurationInstance(),這個可不是我說的,是 Jake Wharton 說的。在上面 Gabor 的帖子上,他的回復(fù)獲得了最多的點贊。雖然我不太贊成 Jake 所說的話,但是我找不到更好的理由去說服自己。這個方法和 ViewModel 后臺使用的原理完全一致,完全沒有理由廢棄掉它。
那我們應(yīng)該怎么對待這些廢棄的方法呢?Google 不管這些方法使用的技術(shù)方案和優(yōu)勢,都強制所有的 Andorid 應(yīng)用遷移到 ViewModel。即使這些方案有可能優(yōu)于 ViewModel 本身,他們也愿意放棄。聽起來有點像是陰謀論吧。
我確實不喜歡保存非配置的狀態(tài),并且廢棄掉對我沒有任何影響,因為我從來都沒有使用過它。事實上,大多數(shù)應(yīng)用程序都不需要這些方法,當然,ViewModel 也不需要。我們需要處理狀態(tài)改變的方法僅僅只有 onSaveInstanceState(Bundle) 這個方法。這個方法非常簡單明了,可以同時處理保存和恢復(fù)的邏輯。所以,只要能用這種方式保存狀態(tài)就可以了,我相信,我不是唯一一個使用這個方法的人。雖然 Google 對 ViewModel 進行了大量的營銷宣傳,但是對于很多經(jīng)驗豐富的開發(fā)者來說, ViewModel 還是太復(fù)雜了,我們有更簡單有效的方法來處理狀態(tài)存儲。
如果 Google 別有用心,想強制所有項目使用 ViewModel , 那么它還將廢棄掉 onSaveInstanceState(Bundle)方法。這聽起來有點不可思議,如果將來真的這樣發(fā)展,那說明我的基礎(chǔ)理論是正確的。
考慮到 Android 的內(nèi)存管理機制,Google 不可能在沒有穩(wěn)定的解決方案之前就廢棄掉 onSaveInstanceState(Bundle) ?!靶疫\的是”,我們已經(jīng)可以使用 ViewModel 來完成相關(guān)工作了。
我想,在一兩年內(nèi),就能看到我的理論是否正確。
總而言之,如在本節(jié)開頭所說,Android 狀態(tài)保存將變成一個爛攤子。兩年多前,我曾經(jīng)寫過 ViewModel 架構(gòu)組件有害的文章[13]時,我就預(yù)測 ViewModel 會對保存與恢復(fù)狀態(tài)的一點點造成影響。我所預(yù)測的都變成了現(xiàn)實,而且現(xiàn)在的情況比我曾經(jīng)的預(yù)測更糟。
并發(fā)
在 Android 并發(fā)編程中,一個重要的 API 就是 AsyncTask, 不過它現(xiàn)在已經(jīng)被棄用掉了。我之前已經(jīng)寫過很詳細的文章分析過它了[14],在這里,將不再贅述。
下面我要說的內(nèi)容,有可能會傷害很多讀者,但是,請不要“恨”我。
RxJava,是一個 Andorid 中常見的多線程框架。但是它現(xiàn)在將逐漸退出歷史的舞臺。從 StackOverflow 的趨勢圖可以看出:
很多開發(fā)者對這個說法提出了質(zhì)疑,他們反駁說這個數(shù)據(jù)不具有代表性,并且我們可以找到其它的理由來解釋圖上所發(fā)生的事情。他們所說可能是正確的,我個人本身也不是數(shù)據(jù)科學(xué)家。但是從圖中我們可以看到,RxJava 與 AsnycTask 有相同的斜率。
如果你沒有時間去學(xué)習(xí) RxJava 如何使用,并且你的項目中也沒有使用過 RxJava,我建議你不要在你的項目中使用 RxJava。事實上,我也一直不推薦使用 RxJava ,現(xiàn)在已經(jīng)有數(shù)據(jù)支持我的這個觀點了。
如果你的項目中使用了 RxJava,你也不用慌張,不需要緊急去重構(gòu)你的項目。如果你的項目只有你一個人,或者整個項目組成員基本不會變動,保持項目現(xiàn)狀就好了。但是你需要記住,以后要招具有 RxJava 開發(fā)經(jīng)驗的人會越來越困難,新招開發(fā)人員可能需要學(xué)習(xí)使用 RxJava。廣泛使用 RxJava 的項目,在以后也會被認為"不酷",就像今天還在使用 AsyncTask 和 Loader 的項目一樣。
我知道,很多 RxJava 的開發(fā)者都是 RxJava 骨灰級的粉絲,他們花了數(shù)周的時間去學(xué)習(xí) RxJava,付出巨大的努力才說服隊友在項目中使用 RxJava?,F(xiàn)在我卻在這里說 RxJava 已經(jīng)過時了。我只能說,這不是我的個人意見,我只是對現(xiàn)有的情況進行分析,并根據(jù)我所看到的內(nèi)容做出預(yù)測。我也有可能是錯的。兩軍交戰(zhàn),不斬來使,請大家不要“攻擊”我。
在 Kotlin 中,使用協(xié)程來實現(xiàn)多并發(fā)。最近使用協(xié)程實現(xiàn)了一些簡單的用例,我發(fā)現(xiàn)它復(fù)雜、不穩(wěn)定,甚至還有一些 Bug。
所有的人都在說,協(xié)程可以降低并發(fā)的復(fù)雜度,使用并發(fā)變得簡單。我從來都不相信這句話,因為我知道并發(fā)從根本上來說就是很復(fù)雜的。我動手寫過一些測試用例過后,據(jù)我的經(jīng)驗,我可以很自信的告訴你,協(xié)程不能使并變得簡單。我認為,協(xié)程會增加復(fù)雜性,我建議你們謹慎使用他們。
在 Kotlin 中,協(xié)程將作為處理多線程的默認方式,如果你已經(jīng)開始使用 Kotlin 進行開發(fā),那么你應(yīng)該花點時間,去學(xué)習(xí)一下,協(xié)程的使用。
據(jù)我所知,還有一個 Flow 框架,它是基于協(xié)程,添加了流運算符。在幾個月之前,已經(jīng)穩(wěn)定了。所以現(xiàn)在也沒啥好評價的。
Kotlin
現(xiàn)在,讓我們來討論一下 Kotlin 在 Android 領(lǐng)域的現(xiàn)狀。根據(jù)我個人的經(jīng)驗來看,這是一個很敏感的話題,不論我所說的話有多么公正客觀,都會有一些粉絲評價我所說的話是“Shit”。但從專業(yè)的角度來說,Kotlin 的話題是跳不過去的,所以,我要強調(diào)的是,這些內(nèi)容只是我的個人觀點,僅供參考。
在 Android 開發(fā)中,使用 Kotlin,會大大地增加你的編譯時間。
在我的另一篇文章中,我統(tǒng)計了使用 Kotlin 過后,編譯時間的增長情況。結(jié)果是,全量編譯的情況下,會增加 18%左右的耗時,如果是增量編譯,則會增加 8% 左右的耗時。
Uber 和 JetBrains 聯(lián)合發(fā)表了他們有關(guān) Kotlin 對項目編譯時間的影響, 在文章中,顯示的結(jié)果非常的悲觀。他們表示,如果你不開啟 IDE 中的 annotation processors ,引入 Kotlin 的項目,編譯構(gòu)建的時間大約會增加四倍,如果開啟了 annotation processors,編譯構(gòu)建的時間也會增加 50% ~ 100%。
Uber 的結(jié)果與 OkHttp 遷移到 Kotlin 后得到的結(jié)果是一致的,都是編譯時長都增加了 4 倍。
別擔心,雖然這個結(jié)果讓人吃驚,這個也不是你的錯,很多人都和你一樣,正在使用 Kotlin。這個問題,雖然很重要,但是它并沒有引起廣泛的關(guān)注。我覺得,Google 也在試圖解決這個問題。我曾問過 Google 相關(guān)的開發(fā)者,并進行了深度的交流,他們在這個問題給我的回答是:“這是一個很棘手的問題,我寧愿不做”。
Kotlin 除了會增加編譯時間,直到上周,才支持增量注解處理,而 Java ,在 10 個月以前就支持了。
在兩年前,我就寫了篇文章用于告誡大家,過早使用 Kotlin 會存在很大的風險。你可以從評論中可以看出,我在很長的一段時間里面,都是“Kotlin 的黑粉”。
在你的實際工作中,你會發(fā)現(xiàn),與上面的數(shù)據(jù)相比,Kotlin 的問題遠不止于此。在大型的 Android 項目中,編譯構(gòu)建的時間會嚴重阻礙項目的發(fā)展。即使到了今天,Kotlin 已經(jīng)被正式使用兩年了,Kotlin 編譯效率依然比 Java 差很多。不管 Kotlin 能給你帶來多少優(yōu)點,編譯耗時的問題,都有可能導(dǎo)致你不在使用它。
不管如何,Google 向整個 Android 的開發(fā)生態(tài)推出 Kotlin 作為第一首選語言,現(xiàn)在 Kotlin 的使用量也越來越大,我們也不得不進行跟進。就我個人而言,我還沒有在我的項目中使用 Kotlin。因為 Kotlin 還不夠成熟,并且我的客戶也不會為我的學(xué)習(xí)付費,并且我也不希望在 Kotlin 上浪費時間。但是從現(xiàn)在開始,Kotlin 已經(jīng)逐漸穩(wěn)定,我也在我拿手的項目上嘗試過, 在新項目中,我也會考慮使用它進行開發(fā)。有一些開發(fā)者認為:“必須在新項目中使用 Kotlin 進行開發(fā)“,我不同意這個觀點,我覺得這是一個權(quán)衡的問題,Kotlin 現(xiàn)在已經(jīng)成為了一個重要的選項,只要適合當前的項目,就是最好的語言。
對于是否要將已有的項目遷移到 Kotlin 上, 我不能給你太好的建議。你需要根據(jù)你項目的情況,具體問題具體分析。如果你一旦決定要進行遷移,這篇文章中列舉的一些可能存在的問題,可能對你有幫助。
總結(jié)
請允許我用 Android 開發(fā)者的背景,描述一下我這兩年所經(jīng)歷的事情:
在過去的兩年里,我啟動了三個項目,我一直爭取,至少參與其中一個項目的開發(fā)工作。我回過頭來看這些已經(jīng)存在的項目,并分析這些項目前期所做的技術(shù)決定對整個項目的影響。我寫了這篇文章,也制作了很多 Android 開發(fā)的高級課程,也花了很多時間在互聯(lián)網(wǎng)上討論 Android 相關(guān)的主題。
即使這樣,我今天依然感覺跟不上 Android 整個生態(tài)系統(tǒng)的變化??上攵?,對于那些經(jīng)驗不足,需要指導(dǎo)的 Android 開發(fā)者而言,是多么地絕望。我現(xiàn)在已經(jīng)無法想像,現(xiàn)在從頭開始學(xué)習(xí) Android 的感覺。當你好不容易學(xué)會了某個框架或者工具,覺得它很好用的時候,它或許就要過時了。現(xiàn)在也許是加入 Android 開發(fā)大家庭最壞的時候。Google 正為他們的“包容性”沾沾自喜,但這一切,對初學(xué)者來說,都是極其痛苦的。
Google 在 Android 框架中所做的事情,會導(dǎo)致大量的時間浪費。我們需要花費數(shù)小時的時間才能讀完所有更改的內(nèi)容,更別說在項目中應(yīng)用它們了。我寧愿花時間來創(chuàng)造價值,而不是舍本逐末。
在本文中,我試圖總結(jié) Android 開發(fā)的現(xiàn)狀,并對未來作出了一些預(yù)測。文章中,可能包含錯誤和漏掉一些重要信息,請隨時在下面的評論中告知我。文章中的內(nèi)容都是客觀內(nèi)容,雖然我提出了一些有爭議觀點,但我相信我是對的。
還有,在文章中,我引用了很多之前寫的帖子,我并不是為了炫耀。而是讓你能夠閱讀之前的預(yù)測與現(xiàn)在的狀況進行對比,雖然那些文章在那個時候讀起來很瘋狂,就像現(xiàn)在你讀本文一樣,但是我的這些預(yù)測都是很準確的。當然,我也想說:“看,我說得對吧”。鑒于我發(fā)布的內(nèi)容具有爭議,當?shù)弥獩]有誤導(dǎo)讀者,我也會感到很欣慰。有時候,我也寧愿我的預(yù)測是錯的,Google 正在為開發(fā)者著想。但是到目前為止,情況并非如此。
結(jié)尾
最后小編想說:不論以后選擇什么方向發(fā)展,目前重要的是把Android方面的技術(shù)學(xué)好,畢竟其實對于程序員來說,要學(xué)習(xí)的知識內(nèi)容、技術(shù)有太多太多,要想不被環(huán)境淘汰就只有不斷提升自己,從來都是我們?nèi)ミm應(yīng)環(huán)境,而不是環(huán)境來適應(yīng)我們!
當程序員容易,當一個優(yōu)秀的程序員是需要不斷學(xué)習(xí)的,從初級程序員到高級程序員,從初級架構(gòu)師到資深架構(gòu)師,或者走向管理,從技術(shù)經(jīng)理到技術(shù)總監(jiān),每個階段都需要掌握不同的能力。早早確定自己的職業(yè)方向,才能在工作和能力提升中甩開同齡人。
相信自己,沒有做不到的,只有想不到的
在這里獲得的不僅僅是技術(shù)!