要點提煉|開發藝術之四大元件

釐米姑娘發表於2018-01-03

提到四大元件大家肯定再熟悉不過了,本篇側重於對四大元件工作過程進行分析:

  • 概述
  • 工作過程
    • Activity
    • Service
    • BroadcastReceiver
    • ContentProvider

1.概述

a.Activity

  • 型別:展示型元件。
  • 作用:展示一個介面並和使用者互動。
  • 使用:
    • 需要在AndroidManifest中註冊。
    • 需要藉助Intent啟動,兩種方式:
      • 顯示Intent: Intent intent=new Intent(xxx.this,xxx.class); startActivity(intent);
      • 隱式Intent: Intent intent=new Intent(); intent.setAction(xxx); intent.addCategory(xxx); startActivity(intent);
    • 四種啟動模式:
      • standard:標準模式
      • singleTop:棧頂複用模式
      • singleTask:棧內複用模式
      • singleInstance:單例項模式
    • 對使用者而言是可見的。
    • 通過finish()結束一個Activity。

相關基礎入門之Activity篇開發藝術之Activity

b.Service

  • 型別:計算型元件。
  • 作用:在後臺執行一系列計算任務,耗時的後臺計算建議在單獨的執行緒中執行。
  • 使用:
    • 需要在AndroidManifest中註冊。
    • 需要藉助Intent啟動: Intent intent = new Intent(xxx.this, xxx.class); startService(intent);
    • 兩種執行狀態:
      • 啟動狀態:通過startService()
      • 繫結狀態:通過bindService()
    • 使用者無法感知。
    • 通過unBindService()stopService()完全停止一個Service。

相關基礎入門之Service篇

c.BroadcastReceiver

  • 型別:訊息型元件。
  • 作用:在不同的元件乃至不同的應用之間傳遞訊息。
  • 使用:
    • 兩種註冊方式:
      • 動態註冊:通過Context.registerReceiver()& Context.unRegisterReceiver(),必須要應用啟動才能註冊並接收廣播。
      • 靜態註冊:在AndroidManifest檔案中註冊,不需要啟動應用即可接收廣播。
    • 需要藉助Intent傳送廣播: Intent intent = new Intent("xxx"); sendBroadcast(intent);
    • 四種廣播型別:
      • 普通廣播
      • 有序廣播
      • 本地廣播
      • 粘性廣播
    • 使用者無法感知。
    • 沒有停止概念。

相關基礎入門之BroadcastReceiver篇

d.ContentProvider

  • 型別:共享型元件。
  • 作用:向其他元件乃至其他應用共享資料。
  • 使用:
    • 需要在AndroidManifest中註冊。
    • 無需藉助Intent啟動。
    • 四種操作:注意需要處理好執行緒同步
      • insert():新增資料
      • update():更新資料
      • delete():刪除資料
      • query():查詢資料
    • 使用者無法感知。
    • 無需手動停止。

相關基礎入門之ContentProvider篇IPC方式之ContentProvider

考考自己android四大元件的執行狀態


二.工作過程

由於相關原始碼非常多,這裡借用@amurocrash的UML圖來提煉流程更為直觀,另附相關原始碼分析的文章供大家詳細瞭解。

a.Activity

Activity啟動過程流程圖:

Activity啟動過程

結論

  • ActivityManagerService、ApplicationThread都是Binder
  • Application的建立也是通過Instrumentation來完成的,這個過程和Activity物件一樣,都是通過類載入器來實現的。
  • Activity的啟動過程最終回到ApplicationThread中,通過ApplicationThread.scheduleLaunchActivity() 將啟動Activity的訊息傳送並交由Handler H處理。
  • Handler H對訊息的處理會呼叫handleLaunchActivity()->performLaunchActivity()得以最終完成Activity的建立和啟動。

原始碼分析Activity的工作過程

b.Service

  • Service啟動過程流程圖:

Service啟動過程

  • Service繫結過程流程圖:

Service繫結過程

結論

  • ContextImpl是Context的具體實現,通過Activity.attach()和Activity建立關聯。Activity.attach()中還會完成Window的建立並和Activity&Window的關聯,由此事件可傳遞給Window。
  • ActivityServices是一個輔助ActivityManagerService(AMS)進行Service管理的類,包括Service的啟動、繫結和停止。
  • 和Activity類似的,Service的啟動/繫結過程最終回到ApplicationThread中,通過ActivityThread.handleCreateService()/ActivityThread.handleBindService完成Service的啟動/繫結,注意繫結Service的後續還必須 告知客戶端已經成功連線Service 的這一流程,由ActivityManagerService.publishService()去完成。

原始碼分析Service的工作過程

c.ContentProvider

  • ContentProvider啟動過程流程圖:

ContentProvider啟動過程

  • 啟動的入口為ActivityThread.main():建立ActivityThread例項並建立主執行緒訊息佇列;
  • ->ActivityThread.attach():遠端呼叫AMS.attachApplication()並提供ApplicationThread用於和AMS的通訊;
  • ->AMS.attachApplication():通過ActivityThread.bindApplication()方法和Handler H來調回ActivityThread.handleBindApplication();
  • ->ActivityThread.handleBindApplication():先建立Application、再載入ContentProvider、最後回撥Application.onCreate()

圖片來源四大元件的工作過程

  • Query過程流程圖:

Query過程

insert()delete()update()類似,這裡不展開

結論

  • ContentProvider的multiprocess屬性:ContentProvider是否是單例,一般用單例。
  • 訪問ContentProvider需要ContentResolver,其真正實現類是ApplicationContentResolver。當ContentProvider所在程式未啟動時,第一次訪問它會觸發ContentProvider的建立以及程式啟動。
  • 當ContentProvider所在的程式啟動時,會同時被啟動並被髮布到AMS中。注意:ContentProvider.onCreate()Application.onCreate()執行。
  • 同樣的,最終通過ActivityThread.handleBindApplication()完成ContentProvider的建立。

原始碼分析 ContentProvider的工作過程

d.BroadcastReceiver

  • 四大元件的靜態註冊都是在應用安裝時由PackageManagerService(PMS)解析註冊,當動態註冊Service時流程為:

Receiver動態註冊過程

  • 廣播傳送和接收過程流程圖:

廣播傳送和接收過程

結論:

  • 動態註冊廣播最終會跨程式交給AMS,並把遠端Receiver( 實際上傳的是IIntentReceiver,是個Binder )物件和遠端IntentFilter儲存起來,完成註冊任務。
  • 傳送廣播時,系統未intent新增了兩個標記位:
    • FLAG_INCLUDE_STOPPED_PACKAGES :廣播也會傳送到已經停止的APP(兩個標記共存時,以該標記為準)
    • FLAG_EXCLUDE_STOPPED_PACKAGES :廣播不會傳送給已經停止的APP(系統為所有廣播預設新增該標記)
  • 最終在ReceiverDispatcher .performReceive ()裡回撥了Receiver 的onReceive(),使得廣播得以接收並處理。

原始碼分析BroadcastReceiver 的工作過程


希望這篇文章對你有幫助~

相關文章