Android如何设计并且实现一个注入框架

2020-04-12  本文已影响0人  风逝_c609

1.小强先定了一个小小的目标,让下面的代码可以直接Run起来

public class MainActivity extends InjectorActivity {

    InjectedObject injectedObject;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 直接调用而不会报空指针异常
        injectedObject.fun();
    }
}
1.1 首先定义个抽象接口
// 成员变量实例注入接口
public interface IMemberInjector<T> {
    /**
     * 给某一个类注入一个实例属性
     * @param instance      该属性的实例
     */
    void injectorMembers(T instance);
}
// 构造实例的工厂接口
public interface IFactory<T> {
    T newInstance();
}

1.2 类注入一个属性实例
public class MainActivityMemberInjector implements IMemberInjector<MainActivity> {

    @Override
    public void injectorMembers(MainActivity instance) {
        setInjectorObject(instance);
        // 其它属性实例注入
    }

    // 注入injectedObject的实例
    private void setInjectorObject(MainActivity instance) {
        instance.injectedObject = new IFactory<InjectedObject>() {

            @Override
            public InjectedObject newInstance() {
                return new InjectedObject();
            }
        }.newInstance();
    }
}

1.3 统一初始化
public class InjectorActivity extends Activity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        InjectorManager.inject(this.getClass().getName());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        InjectorManager.remove(this.getClass().getName());
    }
}
// 完成MemberInjector的注册关系
public class InjectorManager {
    private static Map<String, IMemberInjector> map = new HashMap<>();
    static {
        map.put(MainActivity.class.getName(), new MainActivityMemberInjector());
    }
    public static void inject(String target) {
        if (map.containsKey(target)) {
            IMemberInjector injector = map.get(target);
            injector.injectorMembers(target);
        } else {
            // need register
        }
    }
    public static void remove(String target) {
        map.remove(target);
    }
}

小小的目标瞬间完成Run一把,可以直接调用fun函数运行. 这就是注入的魅力所在有木有把解耦体现的淋漓尽致!!!

在小小的目标完成之后,心里美滋滋的!

可是好景不长,过了几天
除了Activity,其它模块也要注入对象而且注入的对象个数还不止一个
小强心里想,这躲过了被打死,却逃不出要被累死的节奏,怎么办 求生欲满满的......

2. 小强的下一个目标,既要躲过被打死,也要躲过被累死

小强走上了自动化之路(幸福来的太突然了)

2.1 抽取基础功能库
// 包含接口的设计,InjectorActivity, InjectorManager
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Injector {
}
2.2 编译期间生成重复代码
// 通过编译期间生成繁重而又重复木有技术含量的工作
public class MainActivityComponent implements IComponent<MainActivity> {

    @Override
    public void inject(MainActivity instance) {
        // 该字段通过编译期间扫描可以得知并且生成相应的实例注入代码
        instance.injectedObject = new IFactory<InjectedObject>() {

            @Override
            public InjectedObject newInstance() {
                return new InjectedObject();
            }
        }.newInstance();
    }
}
2.3 配置一下直接Run
// 该注解用来描述该字段需要注入实例
public class MainActivity extends InjectorActivity {

    @Injector
    InjectedObject injectedObject;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 操作 injectedObject
    }
}

此后小强过上了既躲过被打死,又躲过了被累死的生活!!!

3. Android Dagger2实践

4. 字节码后记

类别 优缺点 适用
JavaPoet 简单易用 大量的类代码
Javassist 简单易用 大量的类代码(可操作字节码)
ASM 学习成本高 简单的函数调用(APM统计)
上一篇下一篇

猜你喜欢

热点阅读