Dagger2 在 SystemUI 中的应用
return app;}
在 SystemUIApplication onCreate 时回调 ContextAvailableCallback, 构建 SystemUIFactory,并对它进行初始化
src/com/android/systemui/SystemUIFactory.java
public static void createFromConfig(Context context, boolean fromTest) {if (mFactory != null) {return;}
final String clsName = context.getString(R.string.config_systemUIFactoryComponent);if (clsName == null || clsName.length() == 0) {throw new RuntimeException("No SystemUIFactory component configured");}
try {Class<?> cls = null;cls = context.getClassLoader().loadClass(clsName);// 创建 SystemUIFactory 实例 mFactory = (SystemUIFactory) cls.newInstance();// 初始化 SystemUIFactorymFactory.init(context, fromTest);} catch (Throwable t) {Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t);throw new RuntimeException(t);}}
public void init(Context context, boolean fromTest)throws ExecutionException, InterruptedException {...// 获取 dagger 组件 mRootComponent = buildGlobalRootComponent(context);...
// 获取 systemui 的 dagger 组件// And finally, retrieve whatever SysUI needs from WMShell and build SysUI.SysUIComponent.Builder builder = mRootComponent.getSysUIComponent();mSysUIComponent = builder.build();...
// 构建 Dependency 实例并初始化// Every other part of our codebase currently relies on Dependency, so we// really need to ensure the Dependency gets initialized early on.Dependency dependency = mSysUIComponent.createDependency();dependency.start();}
protected GlobalRootComponent buildGlobalRootComponent(Context context) {return DaggerGlobalRootComponent.builder().context(context).build();}
Dependency 组件使用 @Lazy 标签懒加载: 首先构建 LazyDependencyCreator 放入 mProviders,然后在真正使用 dependency 时调用 createDependency 进行创建
src/com/android/systemui/Dependency.java
private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>();private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>();
@Inject Lazy<ActivityStarter> mActivityStarter;@Inject Lazy<BroadcastDispatcher> mBroadcastDispatcher;@Inject Lazy<AsyncSensorManager> mAsyncSensorManager;@Inject Lazy<BluetoothController> mBluetoothController;
protected void start() {// 构建 LazyDependencyCreator 放入 mProvidersmProviders.put(TIME_TICK_HANDLER, mTimeTickHandler::get);mProviders.put(BG_LOOPER, mBgLooper::get);mProviders.put(MAIN_LOOPER, mMainLooper::get);mProviders.put(MAIN_HANDLER, mMainHandler::get);mProviders.put(MAIN_EXECUTOR, mMainExecutor::get);mProviders.put(BACKGROUND_EXECUTOR, mBackgroundExecutor::get);mProviders.put(ActivityStarter.class, mActivityStarter::get);mProviders.put(BroadcastDispatcher.class, mBroadcastDispatcher::get);...
// 获取 dependencyprivate synchronized <T> T getDependencyInner(Object key) {@SuppressWarnings("unchecked")T obj = (T) mDependencies.get(key);if (obj == null) {// 若未创建则创建 obj = createDependency(key);mDependencies.put(key, obj);...}return obj;}
public <T> T createDependency(Object cls) {Preconditions.checkArgument(cls instanceof DependencyKey<?> || cls instanceof Class<?>);
@SuppressWarnings("unchecked")LazyDependencyCreator<T> provider = mProviders.get(cls);if (provider == null) {throw new IllegalArgumentException("Unsupported dependency " + cls
". " + mProviders.size() + " providers known.");}
// 这里调用的就是 lazy.get()return provider.createDependency();}
private interface LazyDependencyCreator<T> {T createDependency();}
ContextComponentResolver
Application 创建好之后 SystemUI 的主 Service 将启动起来,并逐个启动其他 Service。
src/com/android/systemui/SystemUIService.java
public void onCreate() {super.onCreate();// Start all of SystemUI((SystemUIApplication) getApplication()).startServicesIfNeeded();...}
ContextComponentHelper 声明在 dagger 组件中获取,实现类是 ContextComponentResolver
src/com/android/systemui/SystemUIApplication.java
private void startServicesIfNeeded(String metricsPrefix, String[] services) {...final int N = services.length;for (int i = 0; i < N; i++) {String clsName = services[i];if (DEBUG) Log.d(TAG, "loading: " + clsName);log.traceBegin(metricsPrefix + clsName);long ti = System.currentTimeMillis();try {// 从 ContextComponentHelper 中获取对应组件的实例 SystemUI obj = mComponentHelper.resolveSystemUI(clsName);if (obj == null) {Constructor constructor = Class.forName(clsName).getConstructor(Context.class);obj = (SystemUI) constructor.newInstance(this);}mServices[i] = obj;} catch (ClassNotFoundException| NoSuchMethodException| IllegalAccessException| InstantiationException| InvocationTargetException ex) {throw new RuntimeException(ex);}
if (DEBUG) Log.d(TAG, "running: " + mServices[i]);// 调用 SystemUI 组件的 start()方法 mServices[i].start();
ContextComponentHelper 声明在 dagger 组件中获取,实现类是 ContextComponentResolver
src/com/android/systemui/dagger/SysUIComponent.java
@SysUISingletonContextComponentHelper getContextComponentHelper();
@Overridepublic SystemUI resolveSystemUI(String className) {return resolve(className, mSystemUICreators);}
private <T> T resolve(String className, Map<Class<?>, Provider<T>> creators) {try {Class<?> clazz = Class.forName(className);Provider<T> provider = creators.get(clazz);return provider == null ? null : provider.get();} catch (ClassNotFoundException e) {return null;}}
MultiBinding
ContextComponentResolver 的构建方法里,activity、service、systemui 组件、recents 组件、broadcastreceiver 作为参数放到 Map 里储存。
src/com/android/systemui/dagger/ContextComponentResolver.java
@SysUISingletonpublic class ContextComponentResolver implements ContextComponentHelper {priv
ate final Map<Class<?>, Provider<Activity>> mActivityCreators;private final Map<Class<?>, Provider<Service>> mServiceCreContextComponentHelper 声明在 dagger 组件中获取,实现类是 ContextComponentResolverators;private final Map<Class<?>, Provider<SystemUI>> mSystemUICreators;private final Map<Class<?>, Provider<RecentsImplementation>> mRecentsCreators;private final Map<Class<?>, Provider<BroadcastReceiver>> mBroadcastReceiverCreators;
@InjectContextComponentResolver(Map<Class<?>, Provider<Activity>> activityCreators,Map<Class<?>, Provider<Service>> serviceCreators,Map<Class<?>, Provider<SystemUI>> systemUICreators,Map<Class<?>, Provider<RecentsImplementation>> recentsCreators,Map<Class<?>, Provider<BroadcastReceiver>> broadcastReceiverCreators) {mActivityCreators = activityCreators;mServiceCreators = serviceCreators;mSystemUICreators = systemUICreators;mRecentsCreators = recentsCreators;mBroadcastReceiverCreators = broadcastReceiverCreators;}
构建的来源是 systemuicomponent 的各个 module,使用 @IntoMap 和 @ClassKey 进行 MultiBinding
以 SystemUI 组件为例
src/com/android/systemui/dagger/SystemUIBinder.java
@Module(includes = {RecentsModule.class, StatusBarModule.class, KeyguardModule.class})public abstract class SystemUIBinder {/** Inject into AuthController. */@Binds@IntoMap@ClassKey(AuthController.class)public abstract SystemUI bindAuthController(AuthController service);
/** Inject into GarbageMonitor.Service. */@Binds@IntoMap@ClassKey(GarbageMonitor.Service.class)public abstract SystemUI bindGarbageMonitorService(GarbageMonitor.Service sysui);
/** Inject into GlobalActionsComponent. */
评论