前端寫一個月的原生 Android 是怎樣一種體驗?

自從我寫了 Android 應用後,上知乎的時間變得更長了。哦,不對,你理解錯了,我的意思是:編譯代碼、打包 APK、運行在設備上需要時間。可不像前端,一保存代碼,就自動刷新頁面。

是的,從上上週一開始,因為項目缺人的原因,作為一個有 Java 開發經驗的大前端,我又又雙叕進入了原生 Android 開發的世界。

這一個月下來,也算是有一些寫 XML 的心得吧——不對,寫 Java 代碼,看 Kotlin 代碼的心得。總的來說,Android 與前端的差異並不是非常大,在某些東西上,他們還是蠻相似的。怪不得像我這樣的程序員,會將 Android 開發也歸類到大前端上去。

如果你是一個前端程序員,想學習移動開發;又或者是一個移動開發,想接觸前端開發;那麼,本文可能就很適合你去了解兩者間的差異。

本文包含了以下的內容:

  • 編碼效率 vs 可維護度

  • MVP vs MV:後天的 MV*

  • 靜態語言 vs 動態語言

  • View 與 DOM

  • 代碼調試

  • 兼容性

(PS:受限於我只有短暫的經驗,所以有些用詞可能沒有那麼準確。)

:這裡的前端應用特指單頁面應用。

編碼效率 vs 可維護度

因為從運行效率上來說,原生應用必須遠遠大於 WebView——畢竟 WebView 的背後還是原生應用,直接等於中間多了一個層級。所以,在這裡直接討論編碼效率。

前端寫一個月的原生 Android 是怎樣一種體驗?

從編碼效率上來說,還是前端快,快得不止一點點。

  • 更快的預覽速度。

  • 成熟的生態系統。

  • 大量可用的 UI 框架及組件。

  • 參考別家的實現。Web 前端是開放的世界,在今天來看,要實現的效果基本上已經被實現過了,所以我們可以直接參考

  • 富文本支持好

而考慮到 Android 和 iOS 是各自實現的,那麼一個混合應用的開發效率可能是遠遠大於 2 倍,而跨平臺應用(如 React Native、Weex、NativeScript) 的開發效率會接近他們的 2 倍(原因是:集成某些功能時,需要原生代碼來實現,這時工作量直接翻倍等同)。

這篇文章分享之前我還是要推薦下我自己的JAVA群:472052538,不管你是小白還是大牛,小編我都挺歡迎,不定期分享乾貨,包括我自己整理的一份2017最新JAVA資料和零基礎入門教程!,歡迎初學和進階中的小夥伴

前端寫一個月的原生 Android 是怎樣一種體驗?

從目前的維護程度上來說,還是 Java 的代碼相對維護。主要是前端領域的變化太快了,並且在軟件工程上的實踐不像 Java 是必需要求的,因此容易出現大量的遺留代碼。只是考慮到,Java 代碼的臃腫,還是改用 Kotlin 吧。

前端寫一個月的原生 Android 是怎樣一種體驗?

只需要按下: Command + Alt + Shift + K,輕鬆當爸爸。

MVP vs MV:後天的 MV*

MVP,即 Model-View-Presenter,對應於視圖層-數據層-展示層。

在 MVP 上來看,前端應用與 Android 都並非天生的 MVP 架構的。不過,兩者在對業務邏輯上的處理,但是沒有多少差異。唯一能體驗差異的,可能就是 JavaScript 的異步,以及 Java 的同步帶來的一些差別。

V*

採用了框架的前端應用,則會因此而帶上 MV* 的加成。一旦選用上了某個框架,那麼你只能按照其特有的模式,如 Vue 提供的核心是 MVVM 中的 VM,React 則只是 MVC 中的 View 層,則 Angular 則可能是 MVW(Model-View-Whatever)。在這種情況下,要在框架的基本之上變更,那麼靈活性上可能沒有那麼大。

而 Android 方面則是 MVP 架構,其主要依賴於約定俗成,其中一個參考的規範就是 Google 官方的 android-architecture,又或者是社區上推薦的 Clean Architecture。而無論是 Clean Architecture,還是 MVP,其都依賴於約定。一旦我們談及參考的時候,便意味著靈活性——可遵循,可不遵循。

在這種時候,Android 的 MVP 需要我們自己去創建 MVPView,創建 Presenter。

public class MainActivity extends AppCompatActivity implements MainView {
...
}

而整個 MainActivity 只是一個 View 層,真正的業務邏輯要交給 Presenter 來處理。簡單來說,就是你需要手動地創建四五個類,才能完成一個 Activity 的 Hello, world。

Model

與此同時,Android 默認是要對 Model 進行校驗和轉換的。因為取出 JSON 中的某個值,需要將 JSON 轉換為對象——可以直接使用 Retrofit 庫來轉換數據,又或者用 GJSON 轉換成某種對象。算是與前端的一個大的區別,在前端世界裡,這種事情是輕而易舉的,有萬能的

JSON.parse

在使用 JavaScript 編寫的時候,可以不對 Model 進行校驗。不過,在 React 裡會有proptypes,在 Angular 裡可以用 TypeScript 來做相似的事。

與沒有對象校驗的前端相比,一旦出錯,根本不容易察覺。這一點,或者也是一個優勢所在——當你上架了新版本的 API 時,舊的應用不會 NullPointerException。與此同時,在開發的時候,後臺 API 發生變化的時候,也會導致後續的一系列 bug。

靜態語言 vs 動態語言

自從我寫了 Android 應用後,上知乎的時間變得更長了。

編譯與動態運行

當我們編寫 Web 應用的時候,只要一保存代碼,網頁就可以由 LiveReload 這樣的工具來幫我們自動刷新。於是,在諸如 React Native 這樣的跨平臺框架裡,也有 Live Reload 這樣的特性。

而當我開發 Android 應用的時候,每次我想試著在手機上查看效果的時候,得構建、編譯代

當我開發 Android 應用的時候,每次我想試著在手機上查看效果的時候,得構建、編譯代碼、安裝,大概得等上個兩三鍾才能運行在虛擬機或者真機上。

前端寫一個月的原生 Android 是怎樣一種體驗?

可事件往往不會這麼順利,動不動會遇上個 NullPointerException,然後應用就 Crash 了。這個時候,就要去修復代碼中的問題,加個 blabla!=null,然後編譯,繼續 Crash。

怪不得 Android 的程序員喜歡上了 Kotlin,只要一個 view? 就能判斷是不是有值的事:

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { 

val view = inflater?.inflate(R.layout.fragment_home, container, false)
val button: Button = view!!.findViewById(R.id.open_rn_button)
button.setOnClickListener(this)
return view
}

可由於沒有經驗,我經常把 val 寫成了 var。這就和那些習慣寫 alloc init 的 iOS 程序員,一夜間突然喜歡上了寫 ES6 一樣:

let className = NSStringFromClass(MyClass)
let classType = NSClassFromString(className) as? MyClass.Type
if let type = classType {
let my = type.init()
}

哦,不對他們寫的是 Swift。

並且作為一個面向對象的語言,Java 天生就意味著,大量的臃腫代碼。

public int getId() { 
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

大量的代碼,就意味著大量的 bug,一定量的重複代碼,一下子又回到設計模式的天下。

IDE 支持

好在,由於 Android Studio 有強大的、良好的 Intellij 支持。在 IDE 上對語言的支持,要比 JavaScript 的第三方庫支持友好得多:

前端寫一個月的原生 Android 是怎樣一種體驗?

要知道 WebStorm 或者 Intellj IDEA 專業版,它們在 JavaScript 第三方類的支持上就是坑。

View 與 DOM

過去,前端在 DOM 操作上存在天然的問題,即在我們使用 $("*") 的時候,全局。當然現今的框架,在這個問題上比較少,但是考慮到仍然可能會被誤用,或者注入。而 Android 則是局部頁面的。

樣式複用

前端使用 HTML + CSS 來編寫樣式,而安裝則只使用 XML 來切圖,這並不是一件容易的事。不像 CSS 可以通過 “繼承” 和 “覆寫” 的形式來實現樣式複用。Android 中也有類似於 JavaScript 生成 HTML 的方式,自定義模板。

當我們使用 React 編寫組件的時候,可以傳遞對應的屬性到組件中,這個屬性可以是函數、值、組件等等。

MyComponent.propTypes = {
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalElement: PropTypes.element
}

而在 Android 的佈局上,這就不是一樣容易的事。為了複用樣式,需要抽取成 UI 組件,還只能是 UI 上的組件。只能實現 HTML + CSS 上的複用。

HTML + CSS 在編寫 UI 的時候,有各種奇技淫巧,比如說樣式的優先級,或者important

雙向綁定

從原生的角度來看,前端的 document.getElementById() 與 Android 的findViewById 並沒有多大的區別。而當前端有了前端框架之後,就不一樣了。好在 Android 有 ButterKnife 這樣的 View 注入框架。

與此同時,Android 還自帶了雙向的 DataBinding,而原生的前端是沒有的。

只是前端有前端框架,在這一點也完全問題也不多。

佈局調試

還好,已經有寫 React Native 佈局的一些經驗,在寫起 Android 的佈局,倒也還好——沒有那麼坑。

在佈局調試上,還是前端用瀏覽器調式方便——還可以在瀏覽器實時修改 DOM 結構。Android 也有這樣的工具,叫Layout Inspector:

前端寫一個月的原生 Android 是怎樣一種體驗?

除此,還可以通過 Facebook 家的 stetho 做與 Web 相關的調試工作:

前端寫一個月的原生 Android 是怎樣一種體驗?

總的來說,還算是不錯的。就是這個結構,看上去和 React Native 怎麼那麼樣呢?

這篇文章分享之前我還是要推薦下我自己的JAVA群:472052538,不管你是小白還是大牛,小編我都挺歡迎,不定期分享乾貨,包括我自己整理的一份2017最新JAVA資料和零基礎入門教程!,歡迎初學和進階中的小夥伴

代碼調試

在代碼調試上來說,Java 底子厚,總的來說會比 JavaScript 好一些。

前端寫一個月的原生 Android 是怎樣一種體驗?

除此,記得我們在 Chrome 瀏覽器裡可以打斷點,隨後在 Console 中做出一些計算。而得益於 Android Studio 背後的 JetBrain 的 Evaluating Expressions,可以實時計算表達式的值,Android 上的代碼調試也是很容易的。

前端寫一個月的原生 Android 是怎樣一種體驗?

而以我有限的 Objective-C 編程經驗來說,XCode 也是可以做到的。

網絡調試

在 Chrome 瀏覽器裡,自帶的 NetWorks 幾乎是萬能的。Android 方面也可以藉助於Stetho 來使用:

前端寫一個月的原生 Android 是怎樣一種體驗?

但是依賴上比較大,需要在頁面上注入,並且調試不了插件化的應用。要調試網絡吧,還是 Charles 好用一些。

可是,萬一開發環境 HTTPS 了呢,不就更麻煩了。

兼容性

前端面臨的是調試不同的瀏覽器,又或者是兼容 IE。總的來說,問題都不大——不會面臨閃退的問題。即使出了點小問題,用戶可以先換個瀏覽器試試。而當你的 Androdi 應用在用戶的手機上閃退了,那麼用戶只能換個 APP 了。

除此,Android 則是面臨碎片化的系統,不同的版本,及不同的屏幕大小,總的來說,要對前端複雜得多。

結論

Android 在軟件工程上做得相當優秀,而前端則是在開發效率上佔優勢。

Web 開發大法好。


分享到:


相關文章: