赞
踩
学习此知识的前置知识,先学习Dagger2:https://blog.csdn.net/z1804362542/article/details/127268948?spm=1001.2014.3001.5501
本文先从大方向说明Dagger2在SystemUI的结构,后面还会详细说明Dagger2在SystemUI中QS快捷开关的使用
参考:http://events.jianshu.io/p/46a24c3a4a25
**进入正题:**随着SystemServer发出启动SystemUIService的请求,SystemUI的Application将首先被实例化。在实例化之前,指定的AppComponentFactory实现类将会收到回调。
// AndroidManifest.xml
<application
android:name=".SystemUIApplication"
...
tools:replace="android:appComponentFactory"
android:appComponentFactory=".SystemUIAppComponentFactory">
</Application>
调用super执行父类方法得到Application实例app,之后向其注册Context准备完毕的回调,该回调会执行SystemUIFactory和DI组件的初始化。
public class SystemUIAppComponentFactory extends AppComponentFactory { @Inject public ContextComponentHelper mComponentHelper; ... @Override public Application instantiateApplicationCompat( @NonNull ClassLoader cl, @NonNull String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException { Application app = super.instantiateApplicationCompat(cl, className); if (app instanceof ContextInitializer) { // 注册Context成功取得的回调 ((ContextInitializer) app).setContextAvailableCallback( context -> { SystemUIFactory.createFromConfig(context); SystemUIFactory.getInstance().getRootComponent().inject( SystemUIAppComponentFactory.this); } ); } return app; } ... }
回调里先调用createFromConfig创建SystemUIFactory实例,并初始化SystemUI App的Dagger组件。之后初始化DI子组件并向Dependency实例注入依赖。
public class SystemUIFactory { public static void createFromConfig(Context context) { ... try { Class<?> cls = null; cls = context.getClassLoader().loadClass(clsName); // 1. 创建SystemUIFactory实例 mFactory = (SystemUIFactory) cls.newInstance(); //作各种初始化: mFactory.init(context); } } private void init(Context context) { // 2. 取得SystemUI的Dagger组件实例 DaggerSystemUIRootComponent这个东西就是用 //被标准了@Component的SystemUIRootComponent接口自动生成的,该接口是提供依赖 //方和需要依赖方之间的桥梁 mRootComponent = buildSystemUIRootComponent(context); // 3. 创建Dependency实例并绑定到Dependency Injector子组件中 Dependency dependency = new Dependency(); mRootComponent.createDependency().createSystemUI(dependency); // 4. 初始化Dependency dependency.start(); } // 初始化Dagger组件 protected SystemUIRootComponent buildSystemUIRootComponent(Context context) { return DaggerSystemUIRootComponent.builder() .dependencyProvider(new DependencyProvider()) .contextHolder(new ContextHolder(context)) .build(); } ... }
dependency.start() :
Dependency类里掌管着各式各样的依赖,被依赖的各实例通过Map管理。但并不是在初始化的时候就缓存它们。而先将各实例对应的懒加载回调缓存进去。其后在各实例确实需要使用的时候通过注入的懒加载获取和缓存。
这里的Dependency就是扮演者一个依赖需求方的作用
public class Dependency { // 使用class作为key将对应实例缓存的Map private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>(); // 缓存实例的懒加载回调的Map private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>(); ... @Inject Lazy<ActivityStarter> mActivityStarter; @Inject Lazy<BroadcastDispatcher> mBroadcastDispatcher; @Inject Lazy<AsyncSensorManager> mAsyncSensorManager; @Inject Lazy<BluetoothController> mBluetoothController; @Inject Lazy<LocationController> mLocationController; @Inject Lazy<RotationLockController> mRotationLockController; @Inject Lazy<NetworkController> mNetworkController; @Inject Lazy<ZenModeController> mZenModeController; ... /** * Initialize Depenency. */ protected void start() { mProviders.put(TIME_TICK_HANDLER, mTimeTickHandler::get); mProviders.put(BG_LOOPER, mBgLooper::get); mProviders.put(ActivityStarter.class, mActivityStarter::get); mProviders.put(BroadcastDispatcher.class, mBroadcastDispatcher::get); mProviders.put(AsyncSensorManager.class, mAsyncSensorManager::get); mProviders.put(BluetoothController.class, mBluetoothController::get); mProviders.put(RotationLockController.class, mRotationLockController::get); mProviders.put(NetworkController.class, mNetworkController::get); mProviders.put(CastController.class, mCastController::get); mProviders.put(FlashlightController.class, mFlashlightController::get); ... } // 根据class查询缓存,尚未缓存的话通过懒加载回调获取注入的实例并缓存 private synchronized <T> T getDependencyInner(Object key) { T obj = (T) mDependencies.get(key); if (obj == null) { obj = createDependency(key); mDependencies.put(key, obj); if (autoRegisterModulesForDump() && obj instanceof Dumpable) { mDumpManager.registerDumpable(obj.getClass().getName(), (Dumpable) obj); } } return obj; } protected <T> T createDependency(Object cls) { Preconditions.checkArgument(cls instanceof DependencyKey<?> || cls instanceof Class<?>); LazyDependencyCreator<T> provider = mProviders.get(cls); return provider.createDependency(); } private interface LazyDependencyCreator<T> { T createDependency(); } }
那么依赖的提供方,就在每个实例类的构造方法里面的注解:
1、以NetworkController为例子** (这里对应有参构造和使用第三方对象时的注入使用@Bind方式)**
mNetworkController = Dependency.get(NetworkController.class);
与是我们进去Dependency查看
public class Dependency { ... @Inject Lazy<ActivityStarter> mActivityStarter; @Inject Lazy<BroadcastDispatcher> mBroadcastDispatcher; //在这里 依赖需求方 @Inject Lazy<NetworkController> mNetworkController; @Inject Lazy<FlashlightController> mFlashlightController; @Inject Lazy<UserSwitcherController> mUserSwitcherControl ... protected void start() { mProviders.put(NetworkController.class, mNetworkController::get); ...
在整个类中也没有找到关于其实现类NetworkControllerImpl的代码,那它们是如何关联起来的呢?这就是@Inject的作用,类似java后端的@Autowired,具体的作法是,在这里
public class Dependency {
//这里是依赖的需求方
@Inject Lazy<NetworkController> mNetworkController;
然后因为提供方是有参构造,所以需要在module类定义一下提供方,即是DependencyBinder中
@Module(includes = {ControlsModule.class})
public abstract class DependencyBinder {
/**
*/
@Binds
public abstract NetworkController provideNetworkController(
NetworkControllerImpl controllerImpl);
/* 注意这个注解,这样才能实现通过Dependency.java将 NetworkControllerImpl 和 NetWorkController抽象类 关联起来。这样的好处是不用到处通过 NetWorkController mNetWorkController = new NetworkControllerImpl(); 来创建实例 */ @Inject //这里则是依赖的提供方了 public NetworkControllerImpl(Context context, @Background Looper bgLooper, DeviceProvisionedController deviceProvisionedController, BroadcastDispatcher broadcastDispatcher, ConnectivityManager connectivityManager, TelephonyManager telephonyManager, WifiManager wifiManager, NetworkScoreManager networkScoreManager) { this(context, connectivityManager, telephonyManager, wifiManager, networkScoreManager, SubscriptionManager.from(context), Config.readConfig(context), bgLooper, new CallbackHandler(), new AccessPointControllerImpl(context), new DataUsageController(context), new SubscriptionDefaults(), deviceProvisionedController, broadcastDispatcher); mReceiverHandler.post(mRegisterListeners); }
因为NetworkController只有一个实现类NetworkControllerImpl,所以这样即可,如果有多个实现类,还需要其他辅助注解
2、以DataSaverController为例子** (这里对应有参构造和使用第三方对象时的注入使用@Provides方式)**
@Inject Lazy<DataSaverController> mDataSaverController;
mProviders.put(DataSaverController.class, mDataSaverController::get);
我们进入DataSaverController查看,可能会觉得DataSaverControllerImpl实现类即是提供依赖的对象,但是我们进去DataSaverControllerImpl查看发现其构造方法并无@Inject注解
public class DataSaverControllerImpl implements DataSaverController {
public DataSaverControllerImpl(Context context) {
mPolicyManager = NetworkPolicyManager.from(context);
}
...
那么是谁提供了依赖对象呢?根据有参构造和使用第三方对象时的注入方式,可以判断它肯定会有一个moudle类,最后是找到了DependencyProvider
@Module public class DependencyProvider { ... @Singleton @Provides public DataSaverController provideDataSaverController(NetworkController networkController) { return networkController.getDataSaverController(); } ... networkController.getDataSaverController(): 具体实现是实现类networkControllerImpl: private final DataSaverController mDataSaverController; ... mDataSaverController = new DataSaverControllerImpl(context); public DataSaverController getDataSaverController() { return mDataSaverController; } 该类DependencyProvider也是在SystemUI的接口桥梁SystemUIRootComponent类中的@Component包括的 @Component(modules = { ... DependencyProvider.class, ... SystemUIDefaultModule.class}) public interface SystemUIRootComponent { ...
最后,在System UI的任何地方,都能通过 mDataSaverController= Dependency.get(DataSaverController.class); 得到一个实例对象。这个实例对象不是我们DataSaverController mDataSaverController = new DataSaverController();出来的
上面也说了首先构建LazyDependencyCreator放入mProviders,然后在真正使用dependency时调用createDependency进行创建,比如你再其他地方调用了Dependency.get(xxx.class); 那么执行流程是:
/** * @deprecated see docs/dagger.md */ @Deprecated public static <T> T get(Class<T> cls) { /* UNISOC: Bug 1169828 sDependency may be null @{ */ if (sDependency == null) { Log.d(TAG, "get sDependency is null"); return null; } return sDependency.getDependency(cls); } protected final <T> T getDependency(Class<T> cls) { return getDependencyInner(cls); } private synchronized <T> T getDependencyInner(Object key) { @SuppressWarnings("unchecked") T obj = (T) mDependencies.get(key); //这里调用createDependency进行创建了 if (obj == null) { obj = createDependency(key); mDependencies.put(key, obj); // TODO: Get dependencies to register themselves instead if (autoRegisterModulesForDump() && obj instanceof Dumpable) { mDumpManager.registerDumpable(obj.getClass().getName(), (Dumpable) obj); } } return obj; } @VisibleForTesting protected <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."); } return provider.createDependency(); }
好了,我们接下来继续分析Daagger在SystemUI的使用:
Application创建好之后SystemUI的主Service将启动起来,并逐个启动其他Service。
public class SystemUIService extends Service {
...
@Override
public void onCreate() {
super.onCreate();
// Start all of SystemUI
((SystemUIApplication) getApplication()).startServicesIfNeeded();
...
}
}
进入:SystemUIApplication.startServicesIfNeeded :
public class SystemUIApplication {
public void startServicesIfNeeded() {
//getSystemUIServiceComponents就是去加载xml文件的数组string-array name="config_systemUIServiceComponents"
String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());
startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
}
}
配置的Service列表。这里的内容在String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());被加载
// config.xml
<string-array name="config_systemUIServiceComponents" translatable="false">
...
<item>com.android.systemui.recents.Recents</item>
<item>com.android.systemui.volume.VolumeUI</item>
<item>com.android.systemui.stackdivider.Divider</item>
<item>com.android.systemui.statusbar.phone.StatusBar</item> ★
...
</string-array>
进入startServicesIfNeeded里面的startServicesIfNeeded:
通过ContextComponentHelper解析预设的service类名得到实例并启动:
SystemUI obj = mComponentHelper.resolveSystemUI(clsName);
private void startServicesIfNeeded(String metricsPrefix, String[] services) { ... final int N = services.length; for (int i = 0; i < N; i++) { String clsName = services[i]; try { // 从ContextComponentHelper里获取对应的实例, 放到mServices中,然后启动服务 SystemUI obj = mComponentHelper.resolveSystemUI(clsName); if (obj == null) { Constructor constructor = Class.forName(clsName).getConstructor(Context.class); obj = (SystemUI) constructor.newInstance(this); } mServices[i] = obj; } //逐个启动其他service mServices[i].start(); ... } mRootComponent.getInitController().executePostInitTasks(); }
上面说到了 从ContextComponentHelper里获取对应的实例
mComponentHelper.resolveSystemUI(clsName);
ContextComponentHelper单例已声明由Dagger组件提供。
@Singleton @Component(modules = { DefaultComponentBinder.class, DependencyProvider.class, DependencyBinder.class, PipModule.class, SystemServicesModule.class, SystemUIFactory.ContextHolder.class, SystemUIBinder.class, SystemUIModule.class, SystemUIDefaultModule.class}) //SystemUIRootComponent 是 Dagger 注入的根组件。 注意这里用了@Component注解 //@Component 一般用于标注接口,被标注了Component的接口在编译时会产生相应的类的实 //例来作为提供依赖方和需要依赖0方之间的桥梁,把相关依赖注入其中。回去看SystemUIFactory方法, //我们确实发现其在buildSystemUIRootComponent(Context context)中构建生成了一个 //DaggerSystemUIRootComponent.builder() public interface SystemUIRootComponent { ... /** * Creates a ContextComponentHelper. 看这里-------- */ @Singleton ContextComponentHelper getContextComponentHelper(); ... /** * Main dependency providing module. */ @Singleton Dependency.DependencyInjector createDependency(); /** */ @Singleton DumpManager createDumpManager(); /** * FragmentCreator generates all Fragments that need injection. */ @Singleton FragmentService.FragmentCreator createFragmentCreator(); ... }
注解@Component里面包含的模块SystemUIModule就是负责注入ContextComponentHelper实例,我们进去SystemUIModule类查看,通过bindComponentHelper方法可以发现实际执行注入的是ContextComponentResolver类
@Module(...)
public abstract class SystemUIModule {
...
/** */
@Binds
public abstract ContextComponentHelper bindComponentHelper(
ContextComponentResolver componentHelper);
}
ContextComponentResolver用于解析Activity和Service等实例,通过class类名取得class实例再从Map查询得到的Provider里取得对应的Service实例。
它的构造函数注释了@Inject。它依赖几个Map参数,比如StatusBar的Provider是注入到其中的SystemUI Map里。
/** * Used during Service and Activity instantiation to make them injectable. */ @Singleton public class ContextComponentResolver implements ContextComponentHelper { private final Map<Class<?>, Provider<Activity>> mActivityCreators; private final Map<Class<?>, Provider<Service>> mServiceCreators; private final Map<Class<?>, Provider<SystemUI>> mSystemUICreators; private final Map<Class<?>, Provider<RecentsImplementation>> mRecentsCreators; private final Map<Class<?>, Provider<BroadcastReceiver>> mBroadcastReceiverCreators; @Inject ContextComponentResolver(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; } .... /** * Looks up the SystemUI class name to see if Dagger has an instance of it. */ @Override public 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; } } }
构建的来源是SystemUIComponent的各个module,使用@IntoMap和@ClassKey进行MultiBinding
以SystemUI组件为例:src/com/android/systemui/dagger/SystemUIBinder.java
在SystemUIBinder的Module里声明了以ClassKey为StatusBar.class,value由StatusBarPhoneModule模块注入到Map里。而Provider#get()的实例将拿到provideStatusBar注入的实例。
@Module(includes = {RecentsModule.class, StatusBarModule.class...}) // 可注入的 SystemUI 对象应该放在此处。 public abstract class SystemUIBinder { /** Inject into PowerUI. */ @Binds @IntoMap @ClassKey(PowerUI.class) public abstract SystemUI bindPowerUI(PowerUI sysui); /** Inject into StatusBar. */ @Binds @IntoMap @ClassKey(StatusBar.class) public abstract SystemUI bindsStatusBar(StatusBar sysui); ... } 关联的类: @Module(includes = {StatusBarPhoneModule.class...}) public interface StatusBarModule { } @Module(includes = {StatusBarPhoneDependenciesModule.class}) public interface StatusBarPhoneModule { @Provides @Singleton static StatusBar provideStatusBar( Context context, NotificationsController notificationsController, LightBarController lightBarController, AutoHideController autoHideController, KeyguardUpdateMonitor keyguardUpdateMonitor, StatusBarIconController statusBarIconController, ...) { return new StatusBar(...); } }
SystemUI里DI关系图:
不太完善,自己补充画,可使用processon在线画图

首先我们SystemUI的QS是从StatusBar开始的
StatusBar需要用到FragmentHostManager,于是进行
FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
FragmentHostManager.get(container); 方法里面是用Dependency.get懒加载获得FragmentService实例,
public static FragmentHostManager get(View view) {
try {
return Dependency.get(FragmentService.class).getFragmentHostManager(view);
} catch (ClassCastException e) {
throw e;
}
}
fragmentHostManager拿到之后StatusBar就执行相关逻辑。而FragmentService是在Dependency中注入的,然后我们上面get得到。
但要注意的是,当我们get的时候才是真正的执行FragmentService类的构造方法,它里面进行了 mFragmentCreator = rootComponent.createFragmentCreator(); 接口桥梁的创建
@Inject
public FragmentService(SystemUIRootComponent rootComponent,
ConfigurationController configurationController) {
mFragmentCreator = rootComponent.createFragmentCreator();
initInjectionMap();
configurationController.addCallback(mConfigurationListener);
}
这个mFragmentCreator容器在getFragmentCreator返回给出去使用
我们反推是谁使用它
FragmentCreator getFragmentCreator() {
return mFragmentCreator;
}
调用者是:FragmentHostManager.instantiateWithInjections 将构造器传参进入method.invoke,使用反射机制生成Fragment类。然后用传进来的类名进行了实例化
public class FragmentHostManager{ ... class ExtensionFragmentManager { private Fragment instantiateWithInjections(Context context, String className, Bundle args) { Method method = mManager.getInjectionMap().get(className); if (method != null) { try { Fragment f = (Fragment) method.invoke(mManager.getFragmentCreator()); } return f; } //Fragment通过反射创建了一个实例,根据类名className和参数args来创建,其实我们在后面 //调用法会创一个类名QSFragment进来,就是在这里实现QS接口类的注入提供类是QSFragment return Fragment.instantiate(context, className, args); } ... }
我们反推调用方:
public class FragmentHostManager{ ... class ExtensionFragmentManager { Fragment instantiate(Context context, String className, Bundle arguments) { Context extensionContext = mExtensionLookup.get(className); if (extensionContext != null) { Fragment f = instantiateWithInjections(extensionContext, className, arguments); if (f instanceof Plugin) { ((Plugin) f).onCreate(mContext, extensionContext); } return f; } return instantiateWithInjections(context, className, arguments); } } ... } ----------------------------------------------------- public class FragmentHostManager{ ... mPlugins即是ExtensionFragmentManager类 @Override public Fragment instantiate(Context context, String className, Bundle arguments) { return mPlugins.instantiate(context, className, arguments); } ... } -------------------------------------------------- public <T> T create(Class<T> fragmentCls) { return (T) mPlugins.instantiate(mContext, fragmentCls.getName(), null); }
最后发现是有调用方调用了:FragmentHostManager.create,是在StatusBar的下面方法进行了调用
就是在这里,我们传进去了QSFragment.class类名!
protected QS createDefaultQSFragment() { return FragmentHostManager.get(mNotificationShadeWindowView).create(QSFragment.class); } createDefaultQSFragment则是在下面withDefault(this::createDefaultQSFragment)所调用的: protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) { ... // Set up the quick settings tile panel if (container != null) { FragmentHostManager fragmentHostManager = FragmentHostManager.get(container); ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame, mExtensionController .newExtension(QS.class) .withPlugin(QS.class) .withDefault(this::createDefaultQSFragment)//这里! .build()); mBrightnessMirrorController = new BrightnessMirrorController( mNotificationShadeWindowView, ...
总之经过一些列操作,我们的QS类是被创建出来了,并且实现类是QSFragment
这就是虽然QSFragment是有参构造,但我们并没有找到其对应的Moudle类去@provides提供注入给QS,因为是用了上面这种反射方式实现的
@Inject
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
InjectionInflationController injectionInflater, QSTileHost qsTileHost,
StatusBarStateController statusBarStateController, CommandQueue commandQueue,
QSContainerImplController.Builder qsContainerImplControllerBuilder) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
mInjectionInflater = injectionInflater;
mQSContainerImplControllerBuilder = qsContainerImplControllerBuilder;
commandQueue.observe(getLifecycle(), this);
mHost = qsTileHost;
mStatusBarStateController = statusBarStateController;
}
**接下去分析:**然后我们发现QSFragment构造方法里面出现了mHost = qsTileHost、PluginManager pluginManager等依赖。这些依赖比如mHost也并非我们new而来,在这里,mHost就是依赖需求方了,而QSTileHost类的构造方法则是依赖提供方
同样QSTileHost是有参构造,不能直接提供依赖出去,所以它肯定有一个moudle类,是DependencyBinder,借助moudle的来提供出去。但是里面的方法没有使用注解@Providers
**@Binds:**可以理解为关联,首先它是跟@Provider使用地方是一样的,不同的在于@Provides 注解的方法都是有具体实现的,而@Binds修饰的只有方法定义,并没有具体的实现的,在方法定义中方法参数必须是 返回值的实现类。它能够直接关联到实现体的构造方法,但该方法需要加上注解@Inject
在其构造方法发现了@Inject,也是通过直接注入来绑定提供依赖类的。
@Module(includes = {ControlsModule.class})
public abstract class DependencyBinder {
/**
*/
@Binds
public abstract QSHost provideQsHost(QSTileHost controllerImpl);
@Inject public QSTileHost(Context context, StatusBarIconController iconController, QSFactory defaultFactory, @Main Handler mainHandler, @Background Looper bgLooper, PluginManager pluginManager, ... QSLogger qsLogger, UiEventLogger uiEventLogger) { mIconController = iconController; mContext = context; mUiEventLogger = uiEventLogger; mBroadcastDispatcher = broadcastDispatcher; mInstanceIdSequence = new InstanceIdSequence(MAX_QS_INSTANCE_ID); mServices = new TileServices(this, bgLooper, mBroadcastDispatcher); mStatusBarOptional = statusBarOptional; mQsFactories.add(defaultFactory); ... }); }
现在QSTileHost.java类的构造方法里面用到了QSFactory,QSFactory是接口,其注入提供类是QSFactoryImpl,但其构造方法是有参的,所以会有一个moudle类,即是在SystemUIDefaultModule中
@Module(includes = {DividerModule.class})
public abstract class SystemUIDefaultModule {
...
@Binds
@Singleton
public abstract QSFactory provideQSFactory(QSFactoryImpl qsFactoryImpl);
...
}
provideQSFactory()也是通过@Binds来绑定实现注入的
@Inject public QSFactoryImpl(Lazy<QSHost> qsHostLazy, Provider<WifiTile> wifiTileProvider, Provider<BluetoothTile> bluetoothTileProvider, Provider<CellularTile> cellularTileProvider, Provider<DndTile> dndTileProvider, Provider<ColorInversionTile> colorInversionTileProvider, Provider<AirplaneModeTile> airplaneModeTileProvider, Provider<WorkModeTile> workModeTileProvider, Provider<RotationLockTile> rotationLockTileProvider, Provider<SmartProcessControlTile> smartProcessControlTileProvider) { mQsHostLazy = qsHostLazy; mWifiTileProvider = wifiTileProvider; mBluetoothTileProvider = bluetoothTileProvider; mCellularTileProvider = cellularTileProvider; mDndTileProvider = dndTileProvider; mColorInversionTileProvider = colorInversionTileProvider; mAirplaneModeTileProvider = airplaneModeTileProvider; mWorkModeTileProvider = workModeTileProvider; mSmartProcessControlTileProvider = smartProcessControlTileProvider; }
在QSFactoryImpl里面又需要了一大堆实例,Provider的实现方式和前面的可以不太一样,但是我们点进去源码查看,其实就是新加了一些特点,比如可以实现懒加载这些。然后注入的话和上边的差别不大
package javax.inject; /** * Provides instances of {@code T}. Typically implemented by an injector. For * any type {@code T} that can be injected, you can also inject * {@code Provider<T>}. Compared to injecting {@code T} directly, injecting * {@code Provider<T>} enables: {@code Provider<T>}的注入方式比{@code T}的注入方式好在: * * <ul> * <li>retrieving multiple instances.</li> * <li>lazy or optional retrieval of an instance.</li> 懒作或可选的检查实例,可以懒加载的意思把 * <li>breaking circular dependencies.</li> * <li>abstracting scope so you can look up an instance in a smaller scope * from an instance in a containing scope.</li> * </ul> * * <p>For example: * * <pre> * class Car { * @Inject Car(Provider<Seat> seatProvider) { * Seat driver = seatProvider.get(); * Seat passenger = seatProvider.get(); * ... * } * }</pre> */ public interface Provider<T> { T get(); }
以mBluetoothTileProvider = bluetoothTileProvider;为例子
在这里mBluetoothTileProvider 就是依赖需求方,依赖提供方来自BluetoothTile的构造方法
(注意点:虽然Tile类的构造方法是有参数的,但是我们没有写@Proders或者@Binds去提供出去,这是因为使用了第一种无参构造方法的注入形式,即在目标类构造方法加@Inject注解即可。因为虽然是有参构造方法,但是Tile类构造里面并没有使用到第三方依赖jar包等,所需要的类也都是在SystemUI模块里面的。同理,如果你是无参构造方法的注入方式,其实你也可以改成@Providers的形式,总之使用是很灵活的)
@Inject
public QSFactoryImpl(Lazy<QSHost> qsHostLazy,
Provider<BluetoothTile> bluetoothTileProvider){
mQsHostLazy = qsHostLazy;
mBluetoothTileProvider = bluetoothTileProvider;
}
private final BluetoothController mController;
...
@Inject
public BluetoothTile(QSHost host,
BluetoothController bluetoothController,
ActivityStarter activityStarter) {
super(host);
mController = bluetoothController;
mActivityStarter = activityStarter;
mDetailAdapter = (BluetoothDetailAdapter) createDetailAdapter();
mController.observe(getLifecycle(), mCallback);
}
mController = bluetoothController;依赖需求方,提供方又来自BluetoothController的实现类的构造方法
@Inject
public BluetoothControllerImpl(Context context, @Background Looper bgLooper,
@Main Looper mainLooper, @Nullable LocalBluetoothManager localBluetoothManager) {
mLocalBluetoothManager = localBluetoothManager;
mBgHandler = new Handler(bgLooper);
mHandler = new H(mainLooper);
if (mLocalBluetoothManager != null) {
mLocalBluetoothManager.getEventManager().registerCallback(this);
mLocalBluetoothManager.getProfileManager().addServiceListener(this);
onBluetoothStateChanged(
mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState());
}
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mCurrentUser = ActivityManager.getCurrentUser();
}
构造方法是有参数的,所以还是说存在一个modle类,存在于DependencyBinder类,依赖是在这里提供出去的
@Module(includes = {ControlsModule.class})
public abstract class DependencyBinder {
/**
*/
@Binds
public abstract BluetoothController provideBluetoothController(
BluetoothControllerImpl controllerImpl);
疑问:BluetoothTile、TrainTile类中,BluetoothController、TrainController等能否在外面注入,不在构造方法中?
可以,需要进行修改
//提出成员变量,在外面注入 @Inject TrainController trainController; ... //注解不要少加 @Inject public TrainTile(QSHost host,BroadcastDispatcher broadcastDispatcher) { super(host); //重点在这里, trainController.addCallback(this);不能写在构造方法里面 //因为构造方法初始化加载的时候,trainController还没被@Inject注入完成 //会导致trainController实际还是一个接口类被添加到回调集合,最后会导致报错 //trainController.addCallback(this); ... } //比如,我们改成写在这里 @Override public boolean isAvailable() { trainController.addCallback(this); return mContext.getString(R.string.quick_settings_tiles_stock).contains("train"); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。