天天看點

【官網翻譯】性能篇(八)無縫設計

即便您的應用是快速而且響應的,但是某些設計決策仍然可能給使用者帶來問題——因為和其它應用或對話框的非計劃内的互動,無意的資料丢失,不期的阻塞等。為了避免這些問題,您應該努力開發一款與系統和其它應用無縫互動的應用。本文将讨論常見的無縫性問題以及如何避免它們。

前言

       本文翻譯自Android開發者官網的一篇文檔,主要用于介紹關于無縫性設計相關的一些要點。

       中國版官網原文位址為:https://developer.android.google.cn/guide/practices/app-design/seamlessness。

       路徑為:Android Developers > Docs > 指南 > Best practies > Performance > Designing for seamlessness

正文

       即便您的應用是快速而且響應的,但是某些設計決策仍然可能給使用者帶來問題——因為和其它應用或對話框的非計劃内的互動,無意的資料丢失,不期的阻塞,等。為了避免這些問題,它幫助了解應用運作的上下文和可以影響到應用的系統互動。簡而言之,您應該努力開發一款與系統和其它應用無縫互動的應用。

       一個常見的無縫問題是,當應用的背景程序——例如,服務或者廣播接收者——彈出對話框來響應某事件時。這視乎是無害的行為,尤其是當在模拟器上單獨建立及測試應用時。但是,當您的應用在真機上運作的時候,在您的背景程序顯示對話框時,您的應用可能不會擁有使用者焦點。這可能最終變成您的應用在活動的應用後面顯示對話框,或者可能從目前應用擷取焦點,并且在使用者正在進行的任何操作前顯示對話框(例如撥打電話)。那種行為對您的應用或使用者都不起作用。

       為了避免這些問題,您的應用應該使用合适的系統特色來通知使用者——【Notification】類。通過使用通知,當事件發生時您的應用可以示意使用者,在狀态欄上顯示一個圖示而不是搶占焦點并打擾使用者。

      另外一個無縫性問題的例子是,當activity因為沒有正确實作onPause()方法以及其它生命周期方法而無意間丢失狀态或者使用者資料時。或者,如果您的應用暴露資料來給其它應用使用,您應該通過ContentProvider來暴露,而不是(舉個例子)通過全世界都能讀的原始檔案或資料庫來這樣做。

       這些例子有一個共同點是,它們涉及到系統和其它應用良好地協作。Android系統被設計為将應用視為一種松耦合元件的組合,而不是大塊的黑盒子代碼。這允許您作為一個開發者将整個系統視為一個這些元件的更大組合。這通過允許您清晰并無縫地內建其它應用來讓您受益,并且這樣的話您應該設計您自己的代碼來回報這個恩惠。

       本文将讨論常見的無縫性問題以及如何避免它們。

不要丢棄資料

       請時刻謹記,Android是一個移動平台。這說起來很明顯,但是更要的是記住其它Activity(比如“電話來了”應用)可以在任何時刻彈出來覆寫在您自己的Activity上。這将激發onSaveInstanceState()方法和onPause()方法,并且很有可能會導緻您的應用被殺死。

       如果當其它Activity出現時,使用者正在您的應用中編輯資料,當您的應用被殺死時将很有可能丢失那些資料。當然,除非首先儲存正在進行的工作。“Android方式”的做法是:接收或者編輯輸入的Android應用應該重寫onSaveInstanceState()方法并且以适當的方式儲存它們的狀态。當使用者重新通路您的應用時,她應該能夠取回她的資料。

       一個典型的這種行為的良好使用示例是郵件應用。如果當另外一個應用啟動時,使用者正在撰寫郵件,該應用應該将這封正在進行的郵件作為草稿儲存。

不要暴露原始資料

       如果您不會穿着内衣在街上走,那麼您的資料也不應該。因為這有可能暴露某些類型的應用讓全世界讀取,這通常不是最好的主意。暴露原始的資料需要其它應用來了解您的資料格式;如果您改變那個格式,您将破壞其它沒有進行類似更新的應用。

       “Android方式”是建立一個ContentProvider通過清晰、妥當的、可維護的API來将資料暴露給其它應用。使用ContentProvider非常像插入一個Java語言接口來分開并元件化兩個緊耦合的代碼片段。這意味着您将可以修改您的内部資料格式,而不用改變ContentProvider暴露的接口,并且這不會影響其它應用。

不要打擾使用者

       如果使用者正在運作一個應用(比如正在通話時使用電話應用),那麼這是一個非常安全的賭注,他是故意這樣做的。那就是為什麼除了直接響應來自目前Activity的使用者輸入之外,您應該避免生成activity。

       也就是說,不要從正在背景運作的BroadcastReceiver或者Service調用startActivity()。這樣做将中斷目前應用正在運作的工作,并且導緻吵到使用者。可能更嚴重的是,您的Activity可能變成一個“按鍵強盜”并且收到一些使用者正在提供給前一個Activity的輸入資訊。根據您的應用的所作所為,這可能是一個壞消息。

       您應該使用NotificationManager來設定通知,而不是從背景生成Activity使用者界面。這些将會出現在狀态欄,并且使用者可以在空閑的時候點選它們,來看看您的應用給他們顯示了什麼。

       (請注意,所有的這些不适用于您自己的Activity已經在前台的場景:在那些場景中,使用者希望看到您下一個Activity來響應輸入事件。)

有很多事情要做?線上程中完成吧

       如果您的應用需要執行一些昂貴或者長時間運作的計算,您可能應該把它們移動到一個線程中。這将阻止可怕的“應用未響應”對話框顯示給使用者,最終的結果是您的應用火爆地終止了。

       預設情況下,Activity中的所有代碼以及它的所有視圖都運作在相同的線程中。這也是處理UI事件的同一個線程。例如,當使用者按了一個按鍵,按鍵按下事件就被添加到該Activity的主線程隊列中。事件處理系統需要從隊列中取出事件并快速處理它們;如果沒有,幾秒鐘後系統會斷定該應用已經被挂起并且為使用者殺死它。

       如果您有長時間運作的代碼,那麼在Activity中内聯運作它将會在事件處理線程中運作,進而有效地阻塞事件處理。這将延遲輸入處理,并導緻ANR對話框。為了避免這種現象,将計算移動到子線程中。【為響應而設計】文檔中會讨論如何做。

不要過度加載一個單獨的activity螢幕

       所有值得使用的應用可能有多個不同的螢幕。當為您的UI設計螢幕時,確定使用多個Activity對象執行個體。

       根據您開發的背景,您可能解釋Activity為類似于Java Applet的東西,因為它是您應用的入口點。但是,那并不完全正确:Applet子類是Java Applet唯一的入口點,但是Activity應該被認為是可能的進入應用的幾個入口點之一。您“main”Activity和任何其它Activity之間您可能擁有的唯一差别是,“main”Activity碰巧是唯一一個對AndroidManifest.xml檔案中的“android.intent.action.MAIN”行動表達過興趣的Activity。

       是以,當設計應用時,将應用看成是Activity對象的組合。從長遠看,這将會讓您的代碼更加具有可維護性,并且作為一個很好的副作用,它與Android的應用曆史以及“回退棧”模式配合得非常好。

繼承系統主題

       當涉及到使用者接口的外觀和感覺時,重要的是将它們很好地融合在一起。使用者被那些與他們所期望的使用者接口截然不同的應用弄得很煩躁。當設計您的UI時,您應該盡可能嘗試避免滾動您的界面。相反,使用主題。您可以重寫或者繼承那些您需要的主題部分,但至少您正在從和其他應用相同的UI基礎啟動。更多詳情,請查閱【類型和主題】。

設計您的UI來适配多螢幕分辨率

       不同的Android驅動裝置将支援不同的螢幕分辨率。有一些将甚至可能在運作中改變分辨率,比如通過切換到橫屏模式。重要的是確定您的布局和圖檔在不同的裝置螢幕上足夠靈活,以正确顯示。

       幸運的是,這非常容易實作。簡單來說,您必須要做的是為主要分辨率提供不同的圖檔版本(如果您使用任何一個),并且設計您的布局來适配不同的尺寸。(例如,避免使用寫死位置并且使用相對布局。)如果您做了很多,系統會處理剩下的,并且您的應用在任何裝置上都看起來很不錯。

假設網速慢

        Android裝置将會提供各種不同的網絡連接配接選項。所有的這些選項将擁有一些資料通路規定,雖然有些将會比其它的快。可是,最小的公分母是GPRA,這是一種用于GSM網絡的非3G資料服務。即使是支援3G的裝置也将花費很多時間在非3G網絡上,是以在未來很長一段時間緩慢的網絡将仍然是一個事實。  

       那就是為什麼您應該總是編寫您的應用來最小化網絡通路和帶寬。您不能假設網絡是很快的,是以您應該總是為網速變慢做好計劃。如果您的使用者碰巧在更快的網絡,那是很棒的——他們的使用者體驗将隻會提升。不過,您希望避免相反的情況:基于任何給定的時刻使用者所在的位置,部分時間可以使用,但剩餘時間卻非常慢的應用,可能是不受歡迎的。

       這裡有一個潛在的問題是,如果您正在使用模拟器,将很容易掉進這個陷阱,因為模拟器使用的是您的桌面電腦網絡連接配接。那幾乎可以确信比蜂窩網絡快很多,是以您将需要更改模拟器上用來模拟更慢的網絡速度的設定。當啟動模拟器時,您可以在AndroidStudio中通過AVD Manager或者通過【指令行選項】來做這件事。

不要假設觸摸屏或者鍵盤

       Android将會支援多種遙控器形式的因素。那是一種很奇特的說法,某些Android裝置将擁有完整的“QWERTY”的鍵盤,然後其他的裝置将擁有40按鍵,12按鍵,或者甚至其它按鍵配置。相似地,有些裝置将擁有觸摸屏,但是很多卻沒有。

       當建構您的應用時,請記住那些。不用假設特别的鍵盤布局——當然,除非您确實熱衷于限制您的應用以至于讓它隻能在那些裝置上使用。

節省裝置電池

       如果經常被插到牆裡,那麼移動裝置就不那麼移動了。移動裝置是電池驅動的,并且讓電池一次充電後延續的時間越長,所有人就越開心——尤其是使用者。電池電量的兩個最大消費者是處理器和無線通信;那就是為什麼盡可能編寫您的應用來做盡可能少的工作,并且盡可能少地使用網絡是很重要的。

       最小化您應用使用的處理器時間實際上來源于【編寫高效的代碼】。為了最小化來自使用無線電通信的電量流失,請確定優雅地處理錯誤條件,并且隻取您所需要的。例如,如果一次失敗了,不要經常重試網絡操作。如果它失敗了一次,極有可能是因為使用者沒有接收信号,是以如果馬上嘗試,可能将要再次失敗;所有您将做的都是浪費電量。

       使用者時非常明智的:如果您的程式是非常耗電的,您可以指望他們注意到。在那個點上,您唯一能确信的事情是,您的程式安裝時間将不會很長了。

結語 

       本文最大限度保持原文的意思,由于筆者水準有限,若有翻譯不準确或不妥當的地方,請指正,謝謝!