Dagger2在Android11 SystemUI的应用

学习此知识的前置知识,先学习Dagger2:https://blog.csdn.net/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,具体的作法是,在这里

  1. ⽤ @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);
  1. ⽤ @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在线画图
![image.png](https://img-blog.csdnimg.cn/img_convert/b67d17d9e1ee071c40b904977057ad73.png#clientId=u0696a9bf-8690-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown error&from=paste&height=770&id=u06813545&margin=[object Object]&name=image.png&originHeight=770&originWidth=884&originalType=binary&ratio=1&rotation=0&showTitle=false&size=103182&status=error&style=none&taskId=u067eec54-68f6-40dc-83f1-ed4a00ee4de&title=&width=884)

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 {
 *     &#064;Inject Car(Provider&lt;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");
    }
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值