Dagger2在SystemUI中的应用

在SystemUI中,很多的模块都是由DI(依赖注入)的方式来启动的。例如keyguard,StatusBar,Recents。
Dagger2就是助力SystemUI来进行这些复杂的启动。

首先,SystemUI实例的依赖注入管理基本都在Denpency中

public class Dependency {
    ...
    @Inject @Background Lazy<Executor> mBackgroundExecutor;
    @Inject Lazy<ClockManager> mClockManager;
    @Inject Lazy<ActivityManagerWrapper> mActivityManagerWrapper;
    @Inject Lazy<DevicePolicyManagerWrapper> mDevicePolicyManagerWrapper;
    @Inject Lazy<PackageManagerWrapper> mPackageManagerWrapper;
    @Inject Lazy<SensorPrivacyController> mSensorPrivacyController;
    @Inject Lazy<DockManager> mDockManager;
    @Inject Lazy<INotificationManager> mINotificationManager;
    @Inject Lazy<SysUiState> mSysUiStateFlagsContainer;
    @Inject Lazy<AlarmManager> mAlarmManager;
    @Inject Lazy<KeyguardSecurityModel> mKeyguardSecurityModel;
    @Inject Lazy<DozeParameters> mDozeParameters;
    @Inject Lazy<IWallpaperManager> mWallpaperManager;
    @Inject Lazy<CommandQueue> mCommandQueue;
    @Inject Lazy<Recents> mRecents;
    @Inject Lazy<StatusBar> mStatusBar;
    @Inject Lazy<DisplayController> mDisplayController;
    @Inject Lazy<SystemWindows> mSystemWindows;
}

随着SystemServer发出启动SystemUIService的请求,SystemUI的Application将首先被实例化。在实例化之前,指定的AppComponentFactory实现类将会收到回调。

调用super得到Application实例之后向其注册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;
    }
    ...
}

Application的onCreate()回调的时候意味着Context已准备完毕,接着执行上述回调。

public class SystemUIApplication extends Application implements
        SystemUIAppComponentFactory.ContextInitializer {
    ...
    @Override
    public void setContextAvailableCallback(
            SystemUIAppComponentFactory.ContextAvailableCallback callback) {
        mContextAvailableCallback = callback;
    }

    @Override
    public void onCreate() {
        ...
        log.traceBegin("DependencyInjection");
        mContextAvailableCallback.onContextAvailable(this);
        mRootComponent = SystemUIFactory.getInstance().getRootComponent();
        mComponentHelper = mRootComponent.getContextComponentHelper();
        ...
    }
}

回调将先创建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组件实例
        mRootComponent = buildSystemUIRootComponent(context);
        // 3\. 创建Dependency实例并绑定到DependencyInjector子组件中
        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类里掌管着各式各样的依赖,被依赖的各实例通过Map管理。但并不是在初始化的时候就缓存它们。而先将各实例对应的懒加载回调缓存进去。其后在各实例确实需要使用的时候通过注入的懒加载获取和缓存。

public class Dependency {
    // 使用class作为key将对应实例缓存的Map
    private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>();
    // 缓存实例的懒加载回调的Map
    private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>();

    protected void start() {
        mProviders.put(ActivityStarter.class, mActivityStarter::get);
        mProviders.put(Recents.class, mRecents::get);
        mProviders.put(StatusBar.class, mStatusBar::get);
        mProviders.put(NavigationBarController.class, mNavigationBarController::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();
    }
}

Application创建好之后SystemUI的主Service将启动起来,并逐个启动其他Service。

public class SystemUIService extends Service {
    ...
    @Override
    public void onCreate() {
        super.onCreate();
        // Start all of SystemUI
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        ...
    }
}

通过ContextComponentHelper解析预设的service类名得到实例并启动。

public class SystemUIApplication { 
   public void startServicesIfNeeded() {
        String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());
        startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
    }

    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里获取对应的实例
                SystemUI obj = mComponentHelper.resolveSystemUI(clsName);
                if (obj == null) {
                    Constructor constructor = Class.forName(clsName).getConstructor(Context.class);
                    obj = (SystemUI) constructor.newInstance(this);
                }
                mServices[i] = obj;
            }

           mServices[i].start();
             ...
        }
        mRootComponent.getInitController().executePostInitTasks();
       }
}

ContextComponentResolver用于解析Activity和Service等实例,通过class实例从Map查询得到的Provider里取得对应的Service实例。 它的构造函数注释了@Inject。它依赖几个Map参数,比如StatusBar的Provider是注入到其中的SystemUI Map里。

@Singleton
public class ContextComponentResolver implements ContextComponentHelper {
    @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) {
        mSystemUICreators = systemUICreators;
        ...
    }
    ...
    @Override
    public SystemUI resolveSystemUI(String className) {
        return resolve(className, mSystemUICreators);
    }

    // 依据名称得到的class实例去查询Provider实例,进而取得对应SystemUI的实例
    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;
        }
    }
}

总体而言,在Android源码中运用了Dagger2,降低了代码的耦合,实现了代码的复用;类之间通过参数来连接更加的方便;测试更加的便捷

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值