當我還在上大學的時候,Android 和 iOS 還是新興的平臺,每個人都對這兩項技術很感興趣。如果你參加一些當時的編程研討會,最后總會寫一個小型的 Android 應用。這就是我向 Android 生態(tài)系統(tǒng)邁出的第一步,也可能是我隨后成為了一名移動開發(fā)者的原因。 在這篇文章中,我想要分享我關于 Android SDK 和 Flutter 的糟糕體驗。我提到的某些要點也適用于 iOS SDK。我已經在幾年前放棄了移動開發(fā)的工作,希望后來許多事情已經在朝好的方向改進。但在當時,我發(fā)現(xiàn)移動生態(tài)系統(tǒng)是如此的令人感到困惑和挫敗,以至于我選擇了一條不同的職業(yè)路徑。 本文由原作者發(fā)表在 medium.com,經原作者授權由 InfoQ 中文站翻譯并分享 對開發(fā)者而言,Android 開發(fā)的最大痛點,就是設備配置的巨大差異。我一直都未能理解為什么 SDK 中大部分功能(尤其是用戶交互界面的部分)取決于設備,而不是我的應用。這從根本上導致我必須使用支持庫,針對每個目標 API 級別調試我的應用。除此之外,我還經常遇到在仿真器或者測試設備上好好的代碼,卻在某個三星或者華為的設備上崩潰的情況。 質感設計(Material Design)當我在 HackerNews 或者 Reddit 上讀到關于谷歌的 Material Design 的評論時,某些時刻會感到我是唯一真正喜歡它的人。我覺得它在視覺上很具吸引力,我通常很享受這樣的用戶體驗。官方的文檔網站發(fā)展得很快,也非常成功,我覺得這是優(yōu)秀文檔的典范。當它被宣布用于 Android 時,我感到非常興奮! 話雖如此,在 Android 平臺上從 Holo 過渡到 Material Design 并非一帆風順。因為它好像是被急匆匆發(fā)布出來似的。在接下來的幾年之中,官方的 Material Design 支持庫一直缺少一些非?;镜慕M件。雖然你有時可以在谷歌自有的應用上看到這些組件,但是它們并沒有真正被納入到支持庫中。開發(fā)者不得不構建自己的組件,或者使用 GitHub 上質量無法保證的實現(xiàn)作為替代品。這次使用 Material Design 支持庫的經歷,再加上大量的不一致的視覺設計和實現(xiàn)錯誤,讓我第一次停下來真正地思考和質疑這個生態(tài)系統(tǒng)。 構建一個可靠的 Android 應用,是一項充滿挑戰(zhàn)的任務。這主要是因為 SDK 對開發(fā)者并不友好。理論上,一個 Android 應用程序可以永遠掛在后臺不使用任何系統(tǒng)資源,然后在用戶需要時立即回到先前的狀態(tài),這實在是令人驚訝。不過前提是開發(fā)者正確地實現(xiàn)了這個應用的狀態(tài)和生命周期管理機制。
——啊哦,不幸的是,這種回復很普遍。 你是否曾經使用過 Java 中的線程(Threads)?在可變變量隨處可見的的命令式代碼庫中,這件事變得非常困難。但你猜怎么著?在 Android SDK 中使用線程更加困難。如果你想要在一個 Activity 中管理 Thread,那你就只能自求多福了。幸運的是,我們最終保留了 Fragments,這最終讓這件事變得容易了一些。但代價是在一開始就需要使用 Fragments。 在我作為一名移動開發(fā)者的職業(yè)生涯中,我面試了一些高級 Android 開發(fā)者。他們幾乎無一例外,都很難給出這些話題的正確答案。 我一直希望谷歌能更坦然地承認這些問題,并且和社區(qū)一起解決。這些問題可能隨著 Kotlin 的發(fā)布有所改善,但 Android 生態(tài)系統(tǒng)的根基仍然存在很多潛在的問題。 無效的設計模式和對抽象的注解(Annotation)開發(fā)者很快就意識到,在 Android SDK 提供的抽象之上,構建一個真實世界的應用是不可能的。對此的解決方案是層出不窮的設計模式,甚至每周可能都會出現(xiàn)新的設計模式,我記得的包括:MVC、MVP、MVVM 和 MVI。而且由于無法使用普通的構造函數(shù)調用來管理依賴項,我們不得不在代碼庫的每個地方使用注解。這些本來并沒有必要。Java,甚至 Kotlin,本來就有足夠的能力可以對這些東西建模,更何況是以一種透明而直接的方式。但 Android 更喜歡 XML 定義和反射式實例化,因此開發(fā)者不得不在代碼中使用注解和各種設計模式。實話實說,我真的無法形容這到底有多麻煩。 從未利用過的平臺優(yōu)勢在某種程度上,原生 iOS 和 Android 開發(fā)都是作為平臺在與網頁端競爭。但 iOS 和 Android 擁有只屬于一家企業(yè)的巨大的平臺優(yōu)勢,相比之下,網頁端有許多利益相關者,這些利益相關者都想要根據(jù)他們的需要來影響網頁端的開發(fā)。 然而,網頁端擁有更加活躍和創(chuàng)新的生態(tài)系統(tǒng)。只需要想想 React 的成功故事:基于組件的用戶界面,是我們目前提出的最簡潔的抽象方法,這是無可否認的。多年以來,Android 并不理會這一趨勢,直到最近才宣布推出“Jetpack Compose”,但是這仍然僅支持在開發(fā)者預覽模式下使用。同樣的事情也出現(xiàn)在 iOS 開發(fā)中。 所以,現(xiàn)狀是我們仍然需要繼承 android.view.View 類,這個類有 1.5 萬行代碼,和數(shù)十個生命周期函數(shù),但同時我們還要嘗試注入自己的 merge XML 文件。iOS 和 Android 本來可以成為這個競爭中的引領者,但實際上,它們已經被遠遠甩在了后面。 請不要對 UI 開發(fā)抱以希望一個精美的應用的關鍵在于用戶界面(UI)。我在上文已經吐槽了不少關于組件的問題,但這些還不是最嚴重的。你是否曾經調試過網站上的故障?通常的操作是:打開瀏覽器的開發(fā)工具,點擊有問題的元素,然后使用 CSS 和 HTML 的屬性來調試。與此相比,Android 是一個無法訪問的黑盒。老實說,我一直沒有完全理解 Android 的主題和樣式機制,并且與 Web 相比,Android 的工具顯得毫無用處。 矢量圖 在 Android 21(5.0)之前,Android 平臺根本不支持正確的矢量圖。這背后的原因是,多樣的 Android 設備導致了多種不同的屏幕密度,這要求圖像針對每種屏幕密度都做仔細的調整。務實的開發(fā)者自然而然地開發(fā)了轉換矢量圖的工具,將 logo.svg 轉換成 ldpi/logo.png,mdpi/logo.png,hdpi/logo.png,xhdpi/logo.png,xxhdpi/logo.png 以及 xxxhdpi/logo.png。幸運的是,最終谷歌改變了它們的想法,并提供了 VectorDrawble 來支持部分可縮放矢量圖形(SVG)。的確,這足夠減輕當時的痛苦。但仍然令我困惑的是,一個以能夠在任何設備配置上運行為優(yōu)勢的開發(fā)環(huán)境,是如何在這么長時間都不支持矢量圖的情況下活下來的? 死局這些年,我開始越來越擔心我的知識會在不遠的將來過時。我學到的大多數(shù)知識都是 Android 開發(fā)所特有的,很少適用于更廣泛的軟件開發(fā)領域。考慮到這些方面,我不認為原生的移動開發(fā)會一直存在,所以我開始擔心所學到的技能的實用性。 Flutter當 Flutter 發(fā)布時,我非常激動。它承諾將解決一些主要的 Android SDK 的缺陷,同時無償提供跨平臺支持。所以在我上一份工作中,我們開始從原生 Android 遷移到 Flutter 上。我必須承認,F(xiàn)lutter 信守了它的承諾:
但不幸的是,它也不完美。而且有點可惜的是,F(xiàn)lutter 遇到的問題本可以通過一個全新的項目輕松避免。
在某一時刻,我清楚的意識到,我不想在這種技術上傾注心血了。我向自己許諾,絕不再在移動平臺上編程。一個設計精美的、響應式的網站在今天已經可以給你足夠好的體驗,所以這是我的不二之選。只需要一個代碼庫,它就能適用于每個客戶端。如果我還是不得不構建一個移動應用程序,我仍然會選擇 Flutter,甚至是在我僅針對 Android 的情況下。我絕對不會再使用 Android SDK。 話雖如此,但要澄清一點,我還是非常喜愛和欣賞精心制作的原生應用的(無論是在移動設備上還是桌面上)。我對那些使用現(xiàn)有工具就能創(chuàng)建出這樣的應用的開發(fā)者,致以崇高的敬意。只是,我不想再成為他們中的一員。 關注我并轉發(fā)此篇文章,私信我“領取資料”,即可免費獲得InfoQ價值4999元迷你書! |
|