1. 程式人生 > >開發規範:《阿里巴巴Android開發手冊》之初理解

開發規範:《阿里巴巴Android開發手冊》之初理解

今天一早就看見了《阿里巴巴Android開發手冊》開放下載的推送。該開發規範在阿里內部經過了長期的修繕,現已總結成冊,向所有移動開發者、技術愛好者開放,希望幫助開發者碼出高效、碼出質量,提升系統的質量、協作的高效性。粗略翻閱一遍後,總結出部分規範。日後再當細讀。下載地址:《阿里巴巴Android開發手冊》下載

前言

《阿里巴巴 Android 開發手冊》(以下簡稱《手冊》)是阿里各大 Android 開發團隊的集體智慧結晶和經驗總結,將多個 App 長期開發迭代和優化經驗系統地整理成冊,以指導 Android 開發者更加高效、高質量地進行 App 開發。共同遵循同一開發規範,既是高效合作的基礎,也是深度創新的開始。《手冊》遵循《阿里巴巴 Java 開發手冊》手冊下載地址:

https://yq.aliyun.com/articles/693 。以java為開發語言,制定相應規範,對kotlin等並未涉及。目錄結構如下:

《阿里巴巴Android開發手冊》目錄

Android 資原始檔命名與使用

《手冊》中推薦資源命名時增加模組字首,以此區分,方便查詢。drawable 資源名稱以小寫單詞+下劃線的方式命名,根據解析度不同存放在不同的 drawable 目錄下,建議只使用一套,例如 drawable-xhdpi。大解析度圖片(單維度超過 1000)大解析度圖片建議統一放在 xxhdpi 目錄下管理,否則將導致佔用記憶體成倍數增加。

Android 基本元件

Android 基本元件指 Activity、Fragment、Service、BroadcastReceiver、ContentProvider 等。《手冊》進行了17點講解,大致可以從3個角度來進行理解。

從程式碼嚴謹度來考慮:

以下幾點都為了減少bug,因此都為強制:

  • Activity 間的資料通訊,資料量較大時,避免使用 Intent + Parcelable的方式,可以考慮 EventBus 等替代方案,以免造成 TransactionTooLargeException。
  • Activity 間通過隱式 Intent 的跳轉,在發出 Intent 之前必須通過 resolveActivity檢查,避免找不到合適的呼叫元件,造成 ActivityNotFoundException 的異常。
  • 避免在 Service#onStartCommand()/onBind()方法中執行耗時操作,如果確實有需求,應改用 IntentService 或採用其他非同步機制完成。
  • 避免在 BroadcastReceiver#onReceive()中執行耗時操作,如果有耗時工作,應該建立 IntentService 完成,而不應該在 BroadcastReceiver 內建立子執行緒去做。
  • 不要在 Android 的 Application 物件中快取資料。基礎元件之間的資料共享請使用 Intent 等機制,也可使用 SharedPreferences 等資料持久化機制。
  • 使用 Adapter 的時候,如果你使用了 ViewHolder 做快取,在 getView()的方法中無論這項 convertView 的每個子控制元件是否需要設定屬性(比如某個 TextView設定的文字可能為 null,某個按鈕的背景色為透明,某控制元件的顏色為透明等),都需要為其顯式設定屬性(Textview 的文字為空也需要設定 setText(“”),背景透明也需要設定),否則在滑動的過程中,因為 adapter item 複用的原因,會出現內容的顯示錯亂。
  • Activity或者 Fragment 中動態註冊BroadCastReceiver 時,registerReceiver()和 unregisterReceiver()要成對出現。
    說明:如果 registerReceiver()和 unregisterReceiver()不成對出現,則可能導致已經註冊的receiver 沒有在合適的時機登出,導致記憶體洩漏,佔用記憶體空間,加重 SystemService負擔。部分華為的機型會對 receiver 進行資源管控,單個應用註冊過多 receiver 會觸發管控模組丟擲異常,應用直接崩潰。

從效能考慮:

  • 如非必須,避免使用巢狀的 Fragment。
  • 當前Activity的onPause方法執行結束後才會執行下一個Activity的onCreate方法,所以在 onPause 方法中不適合做耗時較長的工作,這會影響到頁面之間的跳轉效率。
  • 對於只用於應用內的廣播,優先使用 LocalBroadcastManager 來進行註冊和傳送,LocalBroadcastManager 安全性更好,同時擁有更高的執行效率。說明:對於使用 Context#sendBroadcast()等方法傳送全域性廣播的程式碼進行提示。如果該廣播僅用於應用內,則可以使用 LocalBroadcastManager 來避免廣播洩漏以及廣播被攔截等安全問題,同時相對全域性廣播本地廣播的更高效。
  • Service 需要以多執行緒來併發處理多個啟動請求,建議使用 IntentService,可避免各種複雜的設定。說明:Service 元件一般執行主執行緒,應當避免耗時操作,如果有耗時操作應該在 Worker執行緒執行。 可以使用 IntentService 執行後臺任務。
  • 總是使用顯式 Intent 啟動或者繫結 Service,且不要為服務宣告 Intent Filter,保證應用的安全性。如果確實需要使用隱式呼叫,則可為 Service 提供 Intent Filter並從 Intent 中排除相應的元件名稱,但必須搭配使用 Intent#setPackage()方法設定Intent 的指定包名,這樣可以充分消除目標服務的不確定性。
  • 不要在 Activity#onDestroy()內執行釋放資源的工作,例如一些工作執行緒的銷燬和停止,因為 onDestroy()執行的時機可能較晚。可根據實際需要,在Activity#onPause()/onStop()中結合 isFinishing()的判斷來執行。
  • 添 加 Fragment 時 , 確 保 FragmentTransaction#commit() 在Activity#onPostResume()或者 FragmentActivity#onResumeFragments()內呼叫。不要隨意使用 FragmentTransaction#commitAllowingStateLoss()來代替,任何commitAllowingStateLoss()的使用必須經過 code review,確保無負面影響。
  • Activity#onSaveInstanceState()方法不是 Activity 生命週期方法,也不保證一定會被呼叫。它是用來在 Activity 被意外銷燬時儲存 UI 狀態的,只能用於儲存臨時性資料,例如 UI 控制元件的屬性等,不能跟資料的持久化儲存混為一談。持久化儲存應該在 Activity#onPause()/onStop()中實行。

從使用者體驗考慮:

  • 使用 Toast 時,建議定義一個全域性的 Toast 物件,這樣可以避免連續顯示Toast 時不能取消上一次 Toast 訊息的情況(如果你有連續彈出 Toast 的情況,避免使用 Toast.makeText)

UI 與佈局:

這部分內容主要是一些基礎規範,比如靈活使用佈局,推薦 Merge、ViewStub 來優化佈局,儘可能多的減少 UI
佈局層級,推薦使用 FrameLayout,LinearLayout、RelativeLayout 次之。