学习此知识的前置知识,先学习Dagger2:https://blog.youkuaiyun.com/z1804362542/article/details/127268948?spm=1001.2014.3001.5501
Dagger2在SystemUI的应用
本文先从大方向说明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,具体的作法是,在这里
- ⽤ @Inject 注解标注⽬标类中依赖类的实例对象 :
public class Dependency {
//这里是依赖的需求方
@Inject Lazy<NetworkController> mNetworkController;
然后因为提供方是有参构造,所以需要在module类定义一下提供方,即是DependencyBinder中
@Module(includes = {ControlsModule.class})
public abstract class DependencyBinder {
/**
*/
@Binds
public abstract NetworkController provideNetworkController(
NetworkControllerImpl controllerImpl);
- ⽤ @Inject 注解标注依赖类的构造函数 :
/* 注意这个注解,这样才能实现通过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在线画图

Dagger2在SystemUI中QS快捷开关的使用:
首先我们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");
}