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 编译期间生成重复代码
- Annotation Processor(注解处理器)
- 自定义Gradle插件
// 通过编译期间生成繁重而又重复木有技术含量的工作
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统计) |
- 用ASM写的一个Gradle插件
ASM字节码插件