Proxy和Delegate的設計思想是相同的,可以壹起討論。前面是代理模式的簡要介紹,後面是具體源碼實戰。
以下基礎知識摘抄自《設計模式-可復用面向對象軟件的基礎》Proxy章節
為其他對象提供壹種代理以控制對這個對象的訪問
當創建某壹具體對象RealSubject開銷很大時,應該根據需要進行創建,當真正需要到這個RealSubject對象時在進行創建,此時就需要用到代理Proxy 。
例如需要在文檔中嵌入 圖形對象的文檔編輯器功能 ,然而 創建圖形文檔編輯器的開銷很大也不是每壹個文檔都需要用到圖形文檔編輯器 。所以我們使用另外壹個對象(即圖像Proxy) 代替 真正的圖形文檔編輯器。 Proxy可以代替壹個圖形文檔編輯器,並且在真正需要的時候負責實例化這個圖形文檔編輯器對象。
只有當文檔編輯器點擊 圖形文檔編輯器 代理Proxy的圖標以啟動功能時,圖形代理Proxy才創建真正的 圖形文檔編輯器 對象
上面說過,代理(委托)模式是為了避免直接創建開銷大的資源而不使用,采用的壹種代理模式以便於真正使用時在實例化。
在 PhoneWindowManager 中使用 KeyguardServiceDelegate 來代理 KeyguardService 的功能( KeyguardService 由 KeyguardServiceWrapper 包裝器進行包裝)
PhoneWindowManager 需要使用到 KeyguardService 的功能,但是在創建 PhoneWindowManager 時就實例化 KeyguardService 沒必要且開銷大,因為還沒用到 KeyguardService 的功能。直接創建 KeyguardService 會浪費 binder線程池 資源,所以應該在需要使用的時候再創建,所以引入 KeyguardServiceDelegate 。
PhoneWindowManager 並沒有直接創建 KeyguardService 對象,而是創建了代理對象 KeyguardServiceDelegate 。 後面 PhoneWindowManager 需要使用到 KeyguardService 的功能時,通過調用 KeyguardServiceDelegate.bindService 將 KeyguardService 的 binder 對象轉化為 接口 封裝到 KeyguardServiceWrapper 包裝器,最後將 KeyguardServiceWrapper 賦值到 KeyguardServiceDelegate 的成員變量,完成整個代理模式的架構。
最終的方法調用流程:
PhoneWindowManager -> KeyguardServiceDelegate ->KeyguardServiceWrapper->KeyguardService
通過創建KeyguardServiceDelegate來避免直接創建KeyguardService而不使用帶來不必要的開銷。屬於延遲加載。
[SystemServer.java]
眾所周知SystemServer用來完成服務的創建和初始化過程。
壹:WindowManagerService.main();啟動了WMS,可以看到new PhoneWindowManager()傳入WMS的main方法中,它將被賦值到成員變量WindowManagerPolicy mPolicy;
二:wm.onInitReady();調用WMS的init方法,這裏是KeyguardServiceDelegate的創建流程
[WindowManagerService.java]
[WindowManagerService.java]
調用PhoneWindowManager.init方法
[PhoneWindowManager.java]
這裏可以看到,在PhoneWindowManager.init函數中並沒有直接創建KeyguardService對象,而是創建了代理對象KeyguardServiceDelegate。在後面需要使用到KeyguardService的功能時,通過調用KeyguardServiceDelegate.bindService將KeyguardService的binder對象轉化為接口封裝到KeyguardServiceWrapper包裝器,最後將包裝器賦值給KeyguardServiceDelegate的成員變量
[KeyguardServiceDelegate.java]
[SystemServer.java]
[SystemServer.java]
[WindowManagerService.java]
mPolicy指的是WindowManagerPolicy。而PhoneWindowManager實現了WindowManagerPolicy接口。mPolicy的賦值在WMS的構造函數中就已經完成了。而WMS的啟動在systemServer中。
[PhoneWindowManager.java]
[PhoneWindowManager.java]
[PhoneWindowManager.java]
調用context.bindServiceAsUser(...)來綁定服務,重點關註以下幾點
通過指定ComponentName來綁定服務。可以看到KeyguardServiceDelegate所在包名為
/frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
尋找resources.getString(com.android.internal.R.string.config_keyguardComponent)的定義位置
[/frameworks/base/core/res/res/values/config.xml]
可以看到config_keyguardComponent對應啟動的就是 KeyguardService 這個服務。通過 ServiceConnection 去指定拿到 KeyguardService 後,將 KeyguardService 轉換為接口對象 IKeyguardService.Stub.asInterface(service) 來創建 KeyguardServiceWrapper 對象。看壹看 KeyguardServiceWrapper 的創建過程
[KeyguardServiceWrapper.java]
可以看到將IKeyguardService service傳遞給了成員變量mService
ServiceConnection mKeyguardConnection 裏通過 KeyguardService 的創建了代理對象 KeyguardServiceWrapper 。
後續當需要使用到 KeyguardService 功能是將是以下的調用過程
PhoneWindowManager -> KeyguardServiceDelegate ->KeyguardServiceWrapper->KeyguardService