bindService 源碼解析(爲什麼是異步)

概述

Andromeda 源碼解析 (同步獲取服務):https://xujiajia.blog.csdn.net/article/details/104166843

前一篇文章分析了Andromeda的源碼,其中提到,bindService獲取IBinder對象的操作是異步的。
那麼爲什麼會是異步的呢,其中做了哪些操作呢?

在此推薦下看Android源碼網站:http://androidxref.com/
(源碼較多的文件建議下載後再本地查看,網頁上看會比較卡)

onServiceConnected的調用棧

首先直接在onServiceConnected中輸出一下調用棧。

     at com.example.bindservicetest.MainActivity$1.onServiceConnected(MainActivity.java:29)
     at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1956)
     at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1988)
     at android.os.Handler.handleCallback(Handler.java:883)
     at android.os.Handler.dispatchMessage(Handler.java:100)
     at android.os.Looper.loop(Looper.java:224)
     at android.app.ActivityThread.main(ActivityThread.java:7520)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

可以看到,最終是調用到了RunConnection這個Runnable。
是通過handle調用的,因此執行是異步的。
那麼在bindService中哪裏會執行到呢?

onServiceConnected在bindService中的調用

由於源碼較多,筆者整理了一下,幾種進入onServiceConnected的調用順序。

Service已經啓動的時候 調用流程

  1. ContextWrapper.bindService()
  2. Context.bindService()
  3. ContextImpl. bindServiceCommon()
  4. ActivityManagerService.bindService()
    (這裏是IPC調用,是異步的)
  5. ActiveService.bindServiceLocked()
  6. LoadedApk.ServiceDispatcher.InnerConnection.connected()
    (這裏是IPC調用,是異步的)
  7. LoadedApk.ServiceDispatcher.connected()
  8. ActivityThread.post()
    (這裏使用到了handle,後面異步)
  9. LoadedApk.ServiceDispatcher. RunConnection.run()
  10. LoadedApk.ServiceDispatcher.doConnected()
  11. ServiceConnection.onServiceConnected()

Service是首次啓動 調用流程

  1. ContextWrapper.bindService()
  2. Context.bindService()
  3. ContextImpl. bindServiceCommon()
  4. ActivityManagerService.bindService()
    (這裏是IPC調用,是異步的)
  5. ActiveService.bindServiceLocked()
  6. ActiveService.requestServiceBindingLocked()
  7. ActivityThread.ApplicationThread.scheduleBindService()
  8. ActivityThread.sendMessage()
    (這裏使用到了handle,後面異步)
  9. ActivityThread.handleBindService()
  10. ActivityManagerService.publishService()
  11. ActiveService.publishServiceLocked()
  12. LoadedApk.ServiceDispatcher.InnerConnection.connected()
    (這裏是IPC調用,是異步的)
  13. LoadedApk.ServiceDispatcher.connected()
  14. ActivityThread.post()
    (這裏使用到了handle,後面異步)
  15. LoadedApk.ServiceDispatcher. RunConnection.run()
  16. LoadedApk.ServiceDispatcher.doConnected()
  17. ServiceConnection.onServiceConnected()

具體分析

根據上面的調用順序,其實大致可以定位異步的原因,即:

InnerConnection的IPC調用,導致回調後的邏輯在binder線程中,因此需要ActivityThread將事件post到主線程執行。

爲什麼InnerConnection會用到IPC?
由於createService和bindService是通過IPC來讓ActivityManagerService實現的,所以在連接建立之後需要再通過IPC來告訴clinet端結果。

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