Dropbox經驗談:iOS和Android的C++跨平臺開發
英文原文:C++ Cross-Platform iOS and Android Development: The Dropbox Lesson
Dropbox 的開發人員最近分享了他們在移動 App 開發方面的經驗。App 如何才能做到同時支持 iOS 和 Android 兩個平臺而又不需要在每個平臺上對相同的功能重復編碼。下面就讓我們詳細了解一下他們為什么這么做,從中得到什么好處以及在這個過程中探索出哪些關鍵經 驗。
幾個月前,Dropbox 的開發人員 Stephen Poletto 和 Sean Beausoleil 在給 非死book 的開發人員做講座時提到,iOS 和 Android 平臺代碼庫的不一致會帶來一系列問題:
- 開發和維護成本成倍增加。
- 開發團隊需要多次修復同樣的缺陷。
- 針對某個平臺報告的缺陷可能會被另一個平臺忽視掉。
- 不同平臺的 App 行為可能會有預料之外的細微差異。
- 性能優化成本高昂并且與平臺相關。 </ul>
- 一個 SQLite 數據庫,扮演著“真相來源”的角色。
- 一個獨立運行的同步服務線程,以保持 Dropbox 服務器和本地 SQLite 數據庫的同步。
- 一個操作隊列,維護所有尚未執行的用戶操作。
- 一個操作線程,負責從操作隊列中提取用戶操作,并在 Dropbox 服務器上執行這些操作。 </ul>
Dropbox 賴以克服上述這些問題的策略基礎就是為所有 UI 無關的代碼建立一個共享的跨平臺 C++ 庫,例如數據和網絡部分的邏輯。UI 部分還是使用原生代碼編寫,以便盡可能地利用平臺對動畫特效和設備傳感器等的支持,并且確保充分的響應速度。
與更傾向用 HTML 5 或 JavaScript 等較抽象語言的自頂向下的方法相對應,Poletto 和 Beausoleil 將這種方式描述為自底向上的方法。據兩位開發人員介紹,這些方法通常難以達到預期的性能要求。
另外一方面,iOS 平臺能夠很好的支持 C++ 代碼,而且這些代碼也可以很方便的與 Objective C++代碼結合。并且,盡管不像 iOS App 那樣方便,Android App 也可以通過 Android 原生開發組件(NDK)使用 C++ 代碼。
在 UIKonf 2014大會上,Mailbox app 的開發者 Steven Kabbes 為聽眾解釋了 Dropbox 開發者如何通過 gyp 來處理 NDK 開發的復雜性,Google 的元構建(meta-build)系統可以用一個 JSON 描述文件生成Xcode 項目,Android 和 Unix 下的 makefile 文件以及 Visual Studio 項目。Steven 還在 GitHub 上發布了一個項目來展示 Dropbox 中使用到的一些跨平臺技術。
C++層的設計
Dropbox 的跨平臺 C++ 層架構比較簡潔,包括:
Dropbox 跨平臺 C++ 層的基本理念是在它和原生代碼之間劃分出明確的邊界。這意味著 C++ 層與 UI 層之間沒有任何數據共享,而且對象的來回復制也要穿過層與層之間的邊界。這種策略的優點在于當涉及到并發時,兩個層次可以被認為是完全獨立的,因此它們不 需要任何跨層的鎖定,并且可以在無需考慮另外一方的情況下處理并發。
Dropbox C++ 層的主要組件是一個由 SQLite 驅動的查詢和持久化框架,讓 Dropbox 開發者可以避免使用 iOS 平臺上的 Core Data 框架。Kabbes 解釋說,Core Data 是一個快速而強大的框架,這個決定并不是由于 Core Data 框架本身的問題,完全是為了滿足同時支持 Android、iOS、Mac 平臺的需求,將來還需要支持 Windows 平臺。這個組件并非為了完全替代 Core Data 框架,而只是提供持久化和查詢的功能,加上用以保證 UI 反應速度的一個組件,即與 NSManagedObjectContextObjectsDidChangeNotification 功能類似的一個 C++ 通知機制。Kabbes 認為這是一個非常關鍵的組件。通過這一機制,只需要傳輸增量的變化。關于持久化組件的更多細節信息可以閱讀 Kabbes 在 GitHub 上的筆記和Ole Begemann 發表的博文。
設計跨平臺 C++ 層時,面臨的一個難題是權衡什么情況下需要從頭開始重新實現 OS 本身已經提供了的功能,什么情況下僅需編寫包裝器(wrapper)封裝這個功能。正如 Poletto 所說,你不可能用 C++ 重新實現整個平臺。因此,對于網絡訪問或 SSL 證書驗證等基礎功能,會通過封裝的方式從 C++ 層回調到原生平臺。Ole Begemann 列舉了幾個例子說明哪些功能不適于重新實現,例如,使用 NSURLSession 進行的后臺下載,App 的后臺行為,以及 iCloud 訪問等。其他一些情況下,則可以重寫那些由平臺相關的 API 所提供的功能,例如 NSUserDefaults 已經被 LevelDB 替換成 Dropbox 的代碼。
據 Poletto 介紹,在 iOS 和 Android 平臺之間共享同一個代碼庫能夠帶來一系列的好處。首先,幾乎可以肯定,iOS 和 Android 團隊之間會有更加緊密的協作。其次,開發團隊能夠更早地捕捉到缺陷,并且可以在兩個平臺上同時修復這些缺陷。再次,性能調優可以同時優化兩個平臺。最 后,Dropbox 可以利用 Android 的 beta 測試程序來測試“iOS 代碼”,這樣就可以立即修復問題而不需要等待 App Store 的審查過程。
<span id="shareA4" class="fl">
</span>