擴展訪問:Uber Lite App開發始末

我們在2016年重寫的Uber乘客App帶來了豐富的功能和流暢的體驗,並支持Uber的一系列產品(從uberPOOL到uberXL)和未來體驗可擴展性(如JUMP Bikes)。Uber乘客App適用於全球市場,支持50種語言和30種支付方式,並且這些數字還在增加中。

儘管我們讓這個App儘可能高效,但它的功能還是導致其體積超過了60MB,使用了更多的網絡帶寬,並要求乘客的手機需要具備特定的硬件性能。

儘管越來越多的全球用戶在使用我們的新App,但我們的數據顯示,拉丁美洲、印度和中東地區的乘客設備和網絡連接常常不能滿足要求。例如,56%的Uber乘客使用2015年版或更早版本的安卓手機。在這樣的硬件上,我們的新乘客App可能無法提供最佳體驗。我們希望爲最廣泛的乘客提供服務,儘可能給他們提供最無縫的交通體驗。

爲了應對這個挑戰,我們構建了Uber Lite(Uber精簡版),這是爲那些使用老款安卓設備以及網絡基礎設施可能無法提供可靠的LTE數據連接的地區而設計的。

圖1 在世界範圍內,40%的Uber乘客使用安卓手機,其硬件相當於2015年或更早的版本

開發Uber Lite背後的動機

2017年,Uber組建了一支團隊,成員來自Uber的研究、設計、產品和工程團隊,旨在解決在低速網絡連接地區使用早期版本安卓設備乘客的痛點。在研究人員和設計人員着手瞭解乘客行爲並提出簡化的用戶界面的同時,工程人員評估了現有的乘客App,看看是否可以通過重構和精簡讓它變得更加輕量一些。

深度工程分析顯示,只是簡單地精簡App是不夠的。相反,我們提出了一個全新的架構,把安卓客戶端的通信職責委派給精心編排的輕量級後端,這個後端專門爲我們基礎架構提供網絡調用服務。這個新的移動後端通信模式和信息架構也可以減少帶寬的使用,而且不會增加安卓應用程序的大小。

我們的工作促成了2018年Uber Lite的發佈,也涉及對全球各地乘客需求的研究,並考慮了他們可用的手機和無線網絡。從一系列嚴格的要求開始,我們的工程團隊定下了設計決策,要最大限度地減少應用程序對手機和網絡資源的需求。Uber Lite反映了我們對超越地區和經濟的交通需求的認識。

產品設計注意事項

我們最新版的乘客App與那些使用最新手機硬件的乘客的需求保持一致,他們能夠訪問快速數據網絡或享受低價的數據套餐。但是,真實世界具有多樣性,數據顯示,僅僅在印度,就有4千6百萬Uber乘客使用安卓手機,這些手機的配置相當於2013年或更早的版本。在世界範圍內,40%的Uber乘客通過安卓手機進行預訂,這些手機的硬件可以追溯到2014年或更早,而33%的預訂是通過3G數據網絡進行的。

針對這些情況,爲了設計一個高性能的應用程序,我們堅持了這三個指導原則:輕量(light)即時(instant)簡單(simple)

輕量

基於我們的研究,我們確定新的App應該具備輕量級的觀感和操作,下載使用儘可能少的帶寬,安裝使用儘可能少的內存。

  • 大小少於5MB:把乘客App的下載包大小保持在5MB以下(所需的內存大小小於三張自拍的大小),保存在設備上的則保持在25MB以下,以加快應用程序的安裝和下載速度,無論網絡環境惡化還是使用2015年或更早的安卓手機都沒關係。

  • 點選地圖:Uber Lite只顯示地圖,乘客在必要時選擇查看基本的實時地圖。這種體驗的前提是減少地圖的使用,以減少對數據網絡的要求。

  • 由****服務器驅動的客戶端:Uber Lite使用了一個服務編排層和後端組件來計算和呈現需要從Uber平臺獲取和編排大量數據的作業。這種工程策略將網絡有效載荷減少到不到1個最大傳輸單元(maximum transmission unit,簡稱MTU)

即時

新的App應該具備很快的響應速度,即使是在3G無線網絡中。

  • 急切****的要求:新的App要求在兩個相繼出現的屏幕之間的切換響應時間不超過300毫秒。

  • 保留單一Dalvik可執行文件(Dalvik Executable,簡稱DEX:在安卓應用程序包(Android application package,簡稱APK)中的方法總數超過65536個時,就會變成多DEX。智能編譯技術的使用與高效庫及獨立設計相結合確保了Uber Lite可以使用單一的DEX,並具有乘客App所有的核心功能。

  • 實時通知:Uber Lite支持實時通知,可以給乘客傳遞重要的告警信息。

簡單

使用一個簡單易懂的5步流程爲乘客帶來良好的使用體驗,這樣可以獲得更好的成行比率(完成的乘行與收到的會話之前的比例),這與使用更強大但在較舊的硬件上或在較慢的網絡中性能不佳的應用程序形成了鮮明對比。

  • 引導式接****車:Uber Lite通過使用興趣點(points of interest,簡稱POI)而不是輸入接車位置簡化了目的地的輸入。POI往往離新興區域的實際位置很近,易於司機辨識,使它們成爲接車的有用地標。

  • 可點擊的目的地:Uber Lite根據乘車人的乘車歷史記錄和乘車頻率呈現目的地列表,並通過緩存它們讓乘客能夠離線訪問並在惡劣的網絡條件下進行快速選擇。新的App用戶界面還可以讓用戶點擊推薦的目的地,而不是讓用戶輸入目的地。

  • 安全:乘客能夠輕鬆地與家人及朋友分享他們的行程,與完整版乘客App中的分享行程狀態功能類似。

  • 語言選擇:本地化是Uber Lite設計的核心,內置了包括葡萄牙語、西班牙語和印地語在內的多種語言。

圖2 Uber Lite使用乘客附近的地標簡化了目的地輸入

App瘦身

對任意一款應用程序來說,各種庫都佔據了很大比例的體積,因此,在構建Uber Lite時,我們非常關注要包含哪些庫。我們仔細評估了大量Uber開發庫及第三方庫的大小、內存和網絡使用量。因爲我們有獨特用例需求,並且對App體積和代碼方法數量有非常激進的目標,所以我們和不同的內部庫作者合作,把它們拆分成更小的模塊,這樣我們就可以只使用真正需要的功能。我們非常謹慎地選擇最基本的已經模塊化的庫。

例如,我們使用RIBs——Uber的一個開源跨平臺移動架構框架——來實現我們的App架構。我們通過RIBs的插件框架將乘客App的核心代碼與非核心代碼區分開來,從而形成一個系統,其中的核心流程(基本功能)可以與非核心代碼完全隔離。不過,這個框架增加了網絡調用有效負載大小。爲了避免Uber Lite也出現這個問題,我們決定不使用RIBs的插件框架。

此外,由於Uber Lite涉及的屏幕切換會少一些,因此,我們只在RIBs屏幕棧中創建了一些小模塊,只包含原生的屏幕切換。這樣就可以去掉大約200KB大小的額外依賴項。

除了限制庫的大小之外,我們還通過以下方式減小Uber Lite的體積:

  • 只傳送特定於應用程序位置的資源(如字符串),以避免應用程序變得太大;

  • 通過Uber現有的linting結構使用矢量圖像格式,避免PNG資源簽入;

  • 從合成訪問器和協變覆蓋等操作生成的Uber Lite字節碼中刪除多餘的方法。

選擇架構設計

通過研究其他公司現有的輕量級應用程序,我們看到了三種設計範式:WebView、帶有服務器渲染UI的原生App架構和標準的原生App架構。在探索了這三種不同的選擇之後,我們決定使用原生App設計。

使用原生shell虛擬機,並從服務器推送內容和UI,這意味着App二進制文件中不包含產品代碼。這個方法的優勢是App的下載包和磁盤佔用空間都很小,並且能夠在不導致原生代碼膨脹的情況下添加新功能。不過,持續向乘客手機推送UI組件會導致網絡開銷變大,因此,我們探索了以下的替代方案:

  • React Native/Flutter:儘管庫很靈活,但其大小在6至8MB之間,所以不考慮這個方法。

  • 通過Uber的移動網站提供WebView:在我們自己開發的Web界面上使用WebView層最初看起來更有吸引力,但在經過試驗之後,我們發現了幾個問題,如:跨不同安卓版本的碎片化問題、無法整合關鍵功能、性能低下,以及難以使用現有的移動基礎設施。

儘管我們決定使用原生App方案,但對於非關鍵流程,我們仍然使用了基於動態UI的框架,這些流程是對核心乘車體驗的輔助,例如支付、幫助和支持。

Uber Lite信息流

對於App來說,最慢的操作通常是從網絡獲取數據,而發展中市場的低網速加劇了這個問題。在構建Uber Lite的信息流時,我們用了8個關鍵設計決策來適應2G網絡:

  • 使用服務器端事件進行後臺更新。後臺更新對於在不影響乘客體驗的情況下保持數據刷新來說是至關重要的。從服務器推送後臺更新讓我們可以掌控更新的時間和頻率。

  • 提前推送信息。上線後立即推送信息(如乘坐的類型和支付選項)可以減少網絡調用開銷,並通過在離線時也能夠在應用程序UI中提供產品信息來改善乘客體驗。

  • 在發生變更時推送信息。我們實時推送有關狀態變化的信息給應用程序,因此,乘客在司機接受其行程時就收到通知。

  • 每個屏幕只允許一個網絡請求。聯合網絡請求可以提高網絡性能,增強乘客體驗。

  • 使用單個TCP連接。在2G網絡上,其上傳速度比下載速度慢得多,單單設置連接就有可能比傳輸數據要耗費更多的時間。保持數據請求和響應的大小少於1個MTU,以確保只使用一個TCP連接就足夠了。

  • 避免冗餘通信。避免重複和不必要的信息可以減少網絡使用。比如,不要進行定時輪詢,而是隻在狀態變化時發送信息,這樣有助於避免冗餘通信。

  • 在後端決定操作。讓後端決定需要嚮應用程序發送什麼內容,而不是在App中進行不必要的計算。

  • 在客戶端緩存數據。Uber Lite緩存靜態數據以避免網絡調用,如特定用戶的產品和支付配置信息。此外,我們還在用戶處於wifi網絡下以及手機電量充足時通過智能緩存位置信息來實現離線搜索。

圖3 Uber Lite預加載數據(如可用的產品類型),以免因過度的網絡調用而給應用程序帶來負擔

接下來要做的事

Uber Lite的旅程纔剛開始,我們看好它的未來前景。隨着時間的推移,我們將繼續構建新的功能,同時尋找方法來控制應用程序的大小,並堅持我們的設計原則:輕量級、即時和簡單。下面,我們來討論一些未來Uber Lite要添加的內容。

用於非常規流的WebView/動態UI

我們開始研究如何爲了某些非常規流在App中使用WebViews或動態UI框架。我們希望在WebView中嘗試不同的緩存策略,讓它們在慢速網絡中更快地運行。優化緩存應該有助於App在不影響其大小的情況下進行擴展。選擇原生體驗還是優化App大小是一種有意識的權衡,我們希望保持本地用戶最重要的流並提供更流暢的體驗。

ProGuard、ReDex和應用程序包

我們也在探索第三方庫瘦身策略。儘管我們可以輕鬆地清除Uber自身的內部庫,但是像ReactiveX和Dagger這樣的開源庫仍然是Uber Lite大小的重要組成部分。我們已經使用ProGuard來優化APK,同時也在積極尋求使用ProGuard和ReDex進行進一步優化。與此同時,我們也在探索新的解決方案(比如App捆綁包)以便能夠快速發佈新功能。

工具

保持小體積的App不是件容易的事情,一次大的提交就可以擺脫我們的大小限制。爲了保持我們的設計原則,我們積極致力於開發工具來避免多DEX文件、生成App大小指標、刪除未使用的依賴項,以及提供依賴包白名單(這些白名單依賴包通過傳遞性避免了多餘的依賴項)。我們還增強了CI管道來拋出這些錯誤,這樣開發人員就可以獲得拉取請求時實時反饋。

查看英文原文:Expanding Access: Engineering Uber Lite

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章