ARouter 第六篇 - 自动注入 (arouter-api)

本系列文章主要分析 ARouter 框架的架构和原理。

这是阿里 ARouter 开源库的地址,大家可以直接访问
https://github.com/alibaba/ARouter

本篇博文主要分析 arouter-api 模块的自动注入原理!

在阅读过程中,涉及到方法跳转的时候,注释上有 -->的标志,这样的好处是,以类为单位,一次性分析其所有的方法:

1 自动注入

我们在跳转的过程中,可能会传递一些数据,在原生的机制里面,我们是通过 Intent 来传递数据的:

1
2
Intent intent = getIntent();
intent.getXXXX();

但是这需要我们手动的获取传递的值,ARouter 提供了一种更方便的方法:自动注入

1
2
3
4
5
6
7
8
9
10
@Autowired
String key1;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test1);

ARouter.getInstance().inject(this);
}

想要实现自动注入,对于变量要通过 @Autowired 注解,同时要使用 ARouter.getInstance().inject(this) 方法关联变量;

其实自动注入依然是通过 intent 来传递值的

2 注解处理 - Autowired

我们来回顾下对于 @Autowired 的处理。

1
2
3
4
5
@AutoService(Processor.class)
@SupportedAnnotationTypes({ANNOTATION_TYPE_AUTOWIRED})
public class AutowiredProcessor extends BaseProcessor {
... ... ...
}

@Autowired 注解是由 AutowiredProcessor 解析并处理,这里我们不再关注注解的处理了,ok?

直接来看生成的类!

2.1 动态生成类

这里我们以 activity 为例子,下面我们一次性把所有可以自动注入的变量类型都加进来;

2.1.1 被注解的类

  • TestInjectActivity,用于接受 intent 传递的值;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
@Route(path = "/test/TestInjectActivity")
public class TestInjectActivity extends Activity {
@Autowired(name = "str1")
String str; // string
@Autowired(name = "bool1")
boolean bool; // boolean
@Autowired(name = "shortNum1")
short shortNum; // short
@Autowired
int intNum; // int
@Autowired
int[] intNumArray; //int[]
@Autowired
long longNum; // long
@Autowired(name = "charStr1")
char charStr; // char
@Autowired(name = "floatNum1")
float floatNum; // float
@Autowired
float[] floatNumArray; // float[]
@Autowired(name = "doubleNum")
double doubleNum; // double

@Autowired(name = "mapStr")
Map<String, String> mapStr; // map
@Autowired
List<TestOne> objList;

@Autowired
TestOne testOne;
@Autowired()
TestOneParcelable testOneParcelable; // Parcelable
@Autowired()
TestTwoParcelable TestTwoParcelable; // Serializable

@Autowired(name = "/test/TestHelloInterface")
HelloInterface helloInterface;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ARouter.getInstance().inject(this); // 自动注入;
}

static class TestOneParcelable implements Parcelable { // 实现了 Parcelable
public String one;
public static final Parcelable.Creator<TestOneParcelable> CREATOR
= new Parcelable.Creator<TestOneParcelable>() {
@Override
public TestOneParcelable createFromParcel(Parcel source) {
return null;
}
@Override
public TestOneParcelable[] newArray(int size) {
return new TestOneParcelable[0];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(one);
}
}

class TestTwoParcelable implements Serializable { // 实现了 Serializable
public String one;
}

class TestOne { // 自定义的类
public String one;
}

interface HelloInterface extends IProvider { // 用于暴漏服务的接口
void sayHello();
}
}

上面是一个 TestInjectActivity 定义了一些需要自动赋值的成员!

  • TestSerializationService:用于序列化自定义的类对象;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Route(path = "/test/TestSerializationService")
public class TestSerializationService implements SerializationService { // 用于序列化自定义对象;
@Override
public <T> T json2Object(String input, Class<T> clazz) {
return null;
}

@Override
public String object2Json(Object instance) {
return null;
}

@Override
public <T> T parseObject(String input, Type clazz) {
return null;
}

@Override
public void init(Context context) {

}
}
  • TestHelloInterface:暴漏的服务,具体的实现。
1
2
3
4
5
6
7
8
9
10
11
@Route(path = "/Test/TestHelloInterface")
public class TestHelloInterface implements TestInjectActivity.HelloInterface { // 用于实现具体的服务;

@Override
public void init(Context context) {
}

@Override
public void sayHello() {
}
}

上面是简单的例子!

2.1.2 动态生成类

我们去看看动态生成的类,动态生成的类所在的包名和自动注入的类的包名是一样的;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class TestInjectActivity$$ARouter$$Autowired implements ISyringe {
private SerializationService serializationService;

@Override
public void inject(Object target) {
//【1】获取序列化服务;
serializationService = ARouter.getInstance().navigation(SerializationService.class);
//【2】获取目标 activity
TestInjectActivity substitute = (TestInjectActivity)target;
//【3】通过 getIntent 来处理传递的数据;
substitute.str = substitute.getIntent().getStringExtra("str1");
substitute.bool = substitute.getIntent().getBooleanExtra("bool1", substitute.bool);
substitute.shortNum = substitute.getIntent().getShortExtra("shortNum1", substitute.shortNum);
substitute.intNum = substitute.getIntent().getIntExtra("intNum", substitute.intNum);
if (null != serializationService) {
substitute.intNumArray = serializationService.parseObject(substitute.getIntent().getStringExtra("intNumArray"),
new com.alibaba.android.arouter.facade.model.TypeWrapper<int[]>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'intNumArray' in class 'TestInjectActivity' "
+ ", then you should implement 'SerializationService' to support object auto inject!");
}
substitute.longNum = substitute.getIntent().getLongExtra("longNum", substitute.longNum);
substitute.charStr = substitute.getIntent().getCharExtra("charStr1", substitute.charStr);
substitute.floatNum = substitute.getIntent().getFloatExtra("floatNum1", substitute.floatNum);
if (null != serializationService) {
substitute.floatNumArray = serializationService.parseObject(substitute.getIntent().getStringExtra("floatNumArray"),
new com.alibaba.android.arouter.facade.model.TypeWrapper<float[]>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'floatNumArray' in class 'TestInjectActivity' "
+ ", then you should implement 'SerializationService' to support object auto inject!");
}
substitute.doubleNum = substitute.getIntent().getDoubleExtra("doubleNum", substitute.doubleNum);
if (null != serializationService) {
substitute.mapStr = serializationService.parseObject(substitute.getIntent().getStringExtra("mapStr"),
new com.alibaba.android.arouter.facade.model.TypeWrapper<Map<String, String>>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'mapStr' in class 'TestInjectActivity' "
+ ", then you should implement 'SerializationService' to support object auto inject!");
}
if (null != serializationService) {
substitute.objList = serializationService.parseObject(substitute.getIntent().getStringExtra("objList"),
new com.alibaba.android.arouter.facade.model.TypeWrapper<List<TestInjectActivity.TestOne>>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'objList' in class 'TestInjectActivity' "
+ ", then you should implement 'SerializationService' to support object auto inject!");
}
if (null != serializationService) {
substitute.testOne = serializationService.parseObject(substitute.getIntent().getStringExtra("testOne"),
new com.alibaba.android.arouter.facade.model.TypeWrapper<TestInjectActivity.TestOne>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'testOne' in class 'TestInjectActivity' "
+ ", then you should implement 'SerializationService' to support object auto inject!");
}
substitute.testOneParcelable = substitute.getIntent().getParcelableExtra("testOneParcelable");
if (null != serializationService) {
substitute.TestTwoParcelable = serializationService.parseObject(substitute.getIntent().getStringExtra("TestTwoParcelable"),
new com.alibaba.android.arouter.facade.model.TypeWrapper<TestInjectActivity.TestTwoParcelable>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'TestTwoParcelable' in class 'TestInjectActivity' "
+ ", then you should implement 'SerializationService' to support object auto inject!");
}
substitute.helloInterface = (TestInjectActivity.HelloInterface)ARouter.getInstance().build("/test/TestHelloInterface").navigation();;
}

其实这个和之前分析注解解析的时候的模版类是一一对应的。

可以看到

  • 基本类型,直接通过 intent 的相关方法来处理;
  • 数组,list,map,自定义类对象,都是通过序列化服务 serializationService 来处理的,也就是说要先将其转为 jsonString,然后保存到 intent 中;

这里我们就不看 AutoWired 的注解解析了,大家可以直接看前面的文章;

3 inject - 自动注入

下面我们来分析下自动注入的流程:

1
ARouter.getInstance().inject(this); // 自动注入;

这个是核心的方法!

3.1 ARouter.inject

1
2
3
4
public void inject(Object thiz) {
//【-->3.2】进入 _ARouter
_ARouter.inject(thiz);
}

3.2 _ARouter.inject

1
2
3
4
5
6
7
8
static void inject(Object thiz) {
//【1】返回 AutowiredServiceImpl 服务
AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
if (null != autowiredService) {
//【-->3.3.1】通过 AutowiredServiceImpl 自动注入
autowiredService.autowire(thiz);
}
}

“/arouter/service/autowired” 对应的 service 是 AutowiredServiceImpl,他是 ARouter 系统 Service,实现了 AutowiredService 接口!

它和 InterceptorServiceImpl 的作用很类似,获取方式这里就不再分析了!

3.3 AutowiredServiceImpl

我们来看看 AutowiredServiceImpl 的属性:

1
2
3
4
@Route(path = "/arouter/service/autowired")
public class AutowiredServiceImpl implements AutowiredService {
private LruCache<String, ISyringe> classCache;
private List<String> blackList;

内部有一个 LruCache 缓存对象:key 是自动注入的类的全限定名(activity/fragment),value 是 activityName$$ARouter$$Autowired 的实例;

黑名单 blackList 用于保存哪些无法自动注入的类,value 是 自动注入的类的全限定名(activity/fragment;

3.3.1 autowire

我们来看看他是如何处理的;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public void autowire(Object instance) {
//【1】获取自动注入的类的全限定名;
String className = instance.getClass().getName();
try {
if (!blackList.contains(className)) {
//【2】判断是否已经添加到了 classCache 缓存中了;
ISyringe autowiredHelper = classCache.get(className);
if (null == autowiredHelper) {
//【3】没有的话就通过反射创建 ISyringe 的实例,其实就是我们解析 AutoWired 的时候生成的:TestInjectActivity$$ARouter$$Autowired
// 这里会创建其实例;
autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
}
//【4】调用其 inject 方法!
autowiredHelper.inject(instance);
//【5】将其加入到缓存中;
classCache.put(className, autowiredHelper);
}
} catch (Exception ex) {
blackList.add(className); // This instance need not autowired.
}
}

SUFFIX_AUTOWIRED 定义在 Consts 中,值为:$$ARouter$$Autowired!!

这里只是用 TestInjectActivity$$ARouter$$Autowire举个例子,实际上这个类的类名、包名和具体的业务相关;

后面的逻辑就不多说了,大家去看 inject 方法,一幕了然!

4 SerializationService

我们来看看如何序列化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Route(path = "/yourservicegroupname/json")
public class JsonServiceImpl implements SerializationService {
@Override
public void init(Context context) {

}

@Override
public <T> T json2Object(String text, Class<T> clazz) {
return JSON.parseObject(text, clazz);
}

@Override
public String object2Json(Object instance) {
return JSON.toJSONString(instance);
}

@Override
public <T> T parseObject(String input, Type clazz) { // TestInjectActivity$$ARouter$$Autowired 使用的是这个方法;
return JSON.parseObject(input, clazz);
}
}

我们需要自己实现一个 SerializationService,前面的动态生成类,使用了 parseObject 方法,将 jsonString 转为了 Object!

5 总结

本篇文章我们分析了 inject 的方法流程,但是我们遗留的下面的问题:

  • ARouter 自动注入的值是如何传递的;

我们会在路由跳转中分析;

文章作者: Coolqi.Li
文章链接: https://lishuaiqi.top/2019/04/30/ARouter6-autoInjectWithAutoWired-arouter-api/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Coolqi`s Blog
支付宝打赏
微信打赏