Android10 SystemUI之Dependency

概述

Dependency是用来封装SystemUI应用中的一些依赖对象。
启动过程:SystemUIApplication的startServicesIfNeeded方法通过反射创建了DependencyCreator的对象,然后调用它的apply方法创建了Dependency对象,最后调用Dependency的start方法完成启动。

DependencyCreator

    public static class DependencyCreator implements Injector {
        @Override
        public SystemUI apply(Context context) {
            Dependency dependency = new Dependency();//创建Dependency对象
            SystemUIFactory.getInstance().getRootComponent()//DaggerSystemUIFactory_SystemUIRootComponent
                    .createDependency()//DaggerSystemUIFactory_SystemUIRootComponent.DependencyInjectorImpl
                    .createSystemUI(dependency);//对dependency 进行初始化
            return dependency;
        }
    }

apply方法主要做的两件事:创建Dependency对象然后通过createSystemUI方法对Dependency对象的属性赋值。

Dependency对象的创建

Dependency关键属性如下:

    //定义一系列DependencyKey对象
    public static final DependencyKey<Looper> BG_LOOPER = new DependencyKey<>(BG_LOOPER_NAME);
    public static final DependencyKey<Handler> BG_HANDLER = new DependencyKey<>(BG_HANDLER_NAME);
    public static final DependencyKey<Handler> TIME_TICK_HANDLER = new DependencyKey<>(TIME_TICK_HANDLER_NAME);
    public static final DependencyKey<Handler> MAIN_HANDLER = new DependencyKey<>(MAIN_HANDLER_NAME);
    public static final DependencyKey<String> LEAK_REPORT_EMAIL = new DependencyKey<>(LEAK_REPORT_EMAIL_NAME);

    private static Dependency sDependency;//单例对象
    private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>();//缓存创建的依赖对象
    private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>();//缓存所有相关的LazyDependencyCreator

    //以下为Lazy对象,在DependencyInjectorImpl的createSystemUI方法中被赋值
    @Inject Lazy<ActivityStarter> mActivityStarter;
    @Inject Lazy<ActivityStarterDelegate> mActivityStarterDelegate;
    @Inject Lazy<AsyncSensorManager> mAsyncSensorManager;
    @Inject Lazy<BluetoothController> mBluetoothController;
    @Inject Lazy<LocationController> mLocationController;
    //...定义各种Lazy对象

DependencyKey封装一个字符串,作为Key来使用,使用泛型来限制Value的类型,代码如下:

    public static final class DependencyKey<V> {
        private final String mDisplayName;

        public DependencyKey(String displayName) {
            mDisplayName = displayName;
        }

        @Override
        public String toString() {
            return mDisplayName;
        }
    }

Lazy提供一个get方法来获取对象。

public interface Lazy<T> {
    T get();
}

LazyDependencyCreator用来创建依赖对象。

    private interface LazyDependencyCreator<T> {
        T createDependency();//此方法返回一个依赖对象
    }

createSystemUI给属性赋值

apply方法中创建了DependencyInjector的实现对象DependencyInjectorImpl,并调用createSystemUI方法对Dependency进行了初始化,相关代码如下:

    @Subcomponent
    public interface DependencyInjector {
        void createSystemUI(Dependency dependency);//此方法的实现会对传入的dependency对象的一系列属性进行赋值。
    }

DependencyInjectorImpl的实现

       public void createSystemUI(Dependency dependency) {
            this.injectDependency(dependency);
        }

        private Dependency injectDependency(Dependency instance) {
            Dependency_MembersInjector.injectMActivityStarter(instance, DoubleCheck.lazy(DaggerSystemUIFactory_SystemUIRootComponent.this.activityStarterDelegateProvider));
            Dependency_MembersInjector.injectMActivityStarterDelegate(instance, DoubleCheck.lazy(DaggerSystemUIFactory_SystemUIRootComponent.this.activityStarterDelegateProvider));
            //...大量类似的inject方法
            return instance;
        }
    }

DoubleCheck.lazy返回Lazy对象,下面是DoubleCheck.lazy方法的实现

    public static <P extends Provider<T>, T> Lazy<T> lazy(P provider) {
        if (provider instanceof Lazy) {
            Lazy<T> lazy = (Lazy)provider;
            return lazy;
        } else {//如果不是Lazy对象,创建DoubleCheck对象返回
            return new DoubleCheck((Provider)Preconditions.checkNotNull(provider));
        }
    }

DoubleCheck实现了Lazy,用于懒创建,get方法第一次调用时获取provider的get返回值,缓存返回值,之后的调用直接使用缓存。

    //DoubleCheck.java
    public T get() {//这个方法实现了双重校验锁,保证对象只会被实例化一次
        Object result = this.instance;
        if (result == UNINITIALIZED) {
            synchronized(this) {
                result = this.instance;
                if (result == UNINITIALIZED) {
                    result = this.provider.get();
                    this.instance = reentrantCheck(this.instance, result);
                    this.provider = null;
                }
            }
        }
        return result;
    }

inject系列的方法主要是给Dependency的属性赋值

    //Dependency_MembersInjector.java
    public static void injectMActivityStarter(Dependency instance, Lazy<ActivityStarter> mActivityStarter) {
        instance.mActivityStarter = mActivityStarter;//给Dependency的属性赋值
    }

     //...

start初始化

 @Override
    public void start() {
        mProviders.put(TIME_TICK_HANDLER, mTimeTickHandler::get);
        mProviders.put(BG_LOOPER, mBgLooper::get);
        mProviders.put(BG_HANDLER, mBgHandler::get);
        mProviders.put(MAIN_HANDLER, mMainHandler::get);
        mProviders.put(ActivityStarter.class, mActivityStarter::get);
        mProviders.put(ActivityStarterDelegate.class, mActivityStarterDelegate::get);
        mProviders.put(AsyncSensorManager.class, mAsyncSensorManager::get);
        mProviders.put(BluetoothController.class, mBluetoothController::get);
        mProviders.put(SensorPrivacyManager.class, mSensorPrivacyManager::get);
        //...缓存各种LazyDependencyCreator
        sDependency = this;
    }

在start方法中将所有的LazyDependencyCreator对象存放在mProviders中,最后给sDependency 赋值,这样,Dependency启动完成。

Dependency关键方法

    @Deprecated
    public static <T> T get(Class<T> cls) {
        return sDependency.getDependency(cls);//静态方法获取依赖对象
    }

    @Deprecated
    public static <T> T get(DependencyKey<T> cls) {
        return sDependency.getDependency(cls);//静态方法获取依赖对象
    }

    protected final <T> T getDependency(Class<T> cls) {
        return getDependencyInner(cls);//获取依赖对象
    }

    protected final <T> T getDependency(DependencyKey<T> key) {
        return getDependencyInner(key);//获取依赖对象
    }

    private synchronized <T> T getDependencyInner(Object key) {
        @SuppressWarnings("unchecked")
        T obj = (T) mDependencies.get(key);//缓存中获取
        if (obj == null) {//没有通过createDependency方法创建
            obj = createDependency(key);
            mDependencies.put(key, 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);//取出LazyDependencyCreator
        if (provider == null) {
            throw new IllegalArgumentException("Unsupported dependency " + cls
                    + ". " + mProviders.size() + " providers known.");
        }
        return provider.createDependency();//创建对象
    }

    private <T> void destroyDependency(Class<T> cls, Consumer<T> destroy) {
        T dep = (T) mDependencies.remove(cls);//从缓存中移除
        if (dep != null && destroy != null) {
            destroy.accept(dep);
        }
    }

当外界请求获取依赖时,从mDependencies缓存中获取,缓存中没有时从mProviders中获取对应的LazyDependencyCreator来获取,并放入mDependencies缓存。

总结

Dependency用来向SystemUI提供一些特定的全局对象,内部维护这些对象的创建者和这些对象的缓存,当需要的对象时,如果缓存没有,由创建者创建对象并存入缓存。
可以通过Class或DependencyKey来获取对象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,183评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,850评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,766评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,854评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,871评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,457评论 1 311
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,999评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,914评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,465评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,543评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,675评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,354评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,029评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,514评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,616评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,091评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,685评论 2 360