概述
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已經啓動的時候 調用流程
- ContextWrapper.bindService()
- Context.bindService()
- ContextImpl. bindServiceCommon()
- ActivityManagerService.bindService()
(這裏是IPC調用,是異步的) - ActiveService.bindServiceLocked()
- LoadedApk.ServiceDispatcher.InnerConnection.connected()
(這裏是IPC調用,是異步的) - LoadedApk.ServiceDispatcher.connected()
- ActivityThread.post()
(這裏使用到了handle,後面異步) - LoadedApk.ServiceDispatcher. RunConnection.run()
- LoadedApk.ServiceDispatcher.doConnected()
- ServiceConnection.onServiceConnected()
Service是首次啓動 調用流程
- ContextWrapper.bindService()
- Context.bindService()
- ContextImpl. bindServiceCommon()
- ActivityManagerService.bindService()
(這裏是IPC調用,是異步的) - ActiveService.bindServiceLocked()
- ActiveService.requestServiceBindingLocked()
- ActivityThread.ApplicationThread.scheduleBindService()
- ActivityThread.sendMessage()
(這裏使用到了handle,後面異步) - ActivityThread.handleBindService()
- ActivityManagerService.publishService()
- ActiveService.publishServiceLocked()
- LoadedApk.ServiceDispatcher.InnerConnection.connected()
(這裏是IPC調用,是異步的) - LoadedApk.ServiceDispatcher.connected()
- ActivityThread.post()
(這裏使用到了handle,後面異步) - LoadedApk.ServiceDispatcher. RunConnection.run()
- LoadedApk.ServiceDispatcher.doConnected()
- ServiceConnection.onServiceConnected()
具體分析
根據上面的調用順序,其實大致可以定位異步的原因,即:
InnerConnection的IPC調用,導致回調後的邏輯在binder線程中,因此需要ActivityThread將事件post到主線程執行。
爲什麼InnerConnection會用到IPC?
由於createService和bindService是通過IPC來讓ActivityManagerService實現的,所以在連接建立之後需要再通過IPC來告訴clinet端結果。