如果對(duì)于 ARouter 不是很了解的,建議先行閱讀:
ARouter系列一:Activity跳轉(zhuǎn)原理詳解
一、Autowaired的 使用及輔助文件類生成
假設(shè)項(xiàng)目中有一個(gè) Activity,名字叫:FirstActivity:
package com.daddyno1.projectmoduledemo;
...
public class FirstActivity extends AppCompatActivity {
@Autowired int age;
@Autowired(name = "name") String mName;
@Autowired Phone phone;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
// 使用ARouter 對(duì)本頁(yè)面的屬性通過傳入的參數(shù)進(jìn)行注入。
ARouter.getInstance().inject(this);
}
}
定義了三個(gè)屬性 age、mName 和 phone,分別用 @Autowired注解,其中Phone是自定義類型,實(shí)現(xiàn)了 Serializable接口。
package com.daddyno1.projectmoduledemo.bean;
...
public class Phone implements Serializable {
public Phone(String type){
this.type = type;
}
public String type;
}
項(xiàng)目編譯,我們看一下,ARouter通過 APT幫助我們生成的輔助類。
在 com.daddyno1.projectmoduledemo 包下生成了 FirstActivity$$ARouter$$Autowired 源文件:
package com.daddyno1.projectmoduledemo;
...
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class FirstActivity$$ARouter$$Autowired implements ISyringe {
private SerializationService serializationService;
@Override
public void inject(Object target) {
serializationService = ARouter.getInstance().navigation(SerializationService.class);
FirstActivity substitute = (FirstActivity)target;
substitute.age = substitute.getIntent().getIntExtra("age", substitute.age);
substitute.mName = substitute.getIntent().getStringExtra("name");
substitute.phone = (com.daddyno1.projectmoduledemo.bean.Phone) substitute.getIntent().getSerializableExtra("phone");
}
}
輔助文件的邏輯很簡(jiǎn)單,通過 Intent 拿到頁(yè)面 FirstActivity 傳遞過來的參數(shù),然后再賦值給 FirstActivity 的屬性。接下來應(yīng)該很明朗了,就是如何使用這個(gè)輔助類呢,通過 反射創(chuàng)建 FirstActivity$$ARouter$$Autowired 對(duì)象,然后調(diào)用其 inject 方法,傳入的參數(shù)就是 FirstActvitiy對(duì)象,這樣 FirstActivity 的屬性就會(huì)自動(dòng)注入值。
因?yàn)槭峭ㄟ^反射創(chuàng)建的輔助類,所以為了提高效率,通過反射創(chuàng)建的
FirstActivity$$ARouter$$Autowired對(duì)象,會(huì)被緩存下來,下次再打開同一個(gè)頁(yè)面,其輔助類的實(shí)例就會(huì)直接從緩存讀取輔助對(duì)象,提高效率。
注意,生成的輔助類名字,都會(huì)以 $$ARouter$$Autowired作為后綴。同時(shí)實(shí)現(xiàn) ISyringe接口:
//抽象了一個(gè)注入的方法
public interface ISyringe {
void inject(Object target);
}
二、ARouter 的注入邏輯源碼分析
我們?cè)?FirstActiviy 中使用 ARouter.getInstance().inject(this); 就會(huì)實(shí)現(xiàn)屬性自動(dòng)注入。接下來分析一下如何實(shí)現(xiàn)的。之后會(huì)調(diào)用 _ARouter#inject
final class _ARouter{
static void inject(Object thiz) {
//獲取 AutowiredService 的接口實(shí)現(xiàn),拿到最終進(jìn)行注入的服務(wù)實(shí)現(xiàn)
AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
if (null != autowiredService) {
//實(shí)現(xiàn)注入
autowiredService.autowire(thiz);
}
}
}
通過 /arouter/service/autowired 最終拿到的 AutowiredService 接口實(shí)現(xiàn)類是 AutowiredServiceImpl,AutowiredServiceImpl 封裝了對(duì)于所有 Activity 進(jìn)行屬性注入的邏輯處理。
package com.alibaba.android.arouter.core;
...
@Route(path = "/arouter/service/autowired")
public class AutowiredServiceImpl implements AutowiredService {
/**這是一個(gè)緩存,key:被注入的Activity全類名,value:此Activity輔助類實(shí)例。因?yàn)檩o助類的實(shí)例
通過反射獲取,消耗性能,這樣緩存起來,下次再進(jìn)入頁(yè)面的時(shí)候就會(huì)快。
**/
private LruCache<String, ISyringe> classCache;
private List<String> blackList;
@Override
public void init(Context context) {
classCache = new LruCache<>(66);
blackList = new ArrayList<>();
}
@Override
public void autowire(Object instance) {
// 所要注入的Activity的全類名: com.daddyno1.projectmoduledemo.FirstActivity
String className = instance.getClass().getName();
try {
// 如果 所要注入的類的全類名在黑名單中,則不進(jìn)行屬性自動(dòng)注入。
if (!blackList.contains(className)) {
//從緩存中獲取輔助類對(duì)象
ISyringe autowiredHelper = classCache.get(className);
if (null == autowiredHelper) { // No cache.
//如果沒緩存,則反射構(gòu)建輔助類對(duì)象。如:com.daddyno1.projectmoduledemo.FirstActivity$$ARouter$$Autowired
autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
}
// 調(diào)用注入。如:FirstActivity$$ARouter$$Autowired.inject
autowiredHelper.inject(instance);
//放入緩存
classCache.put(className, autowiredHelper);
}
} catch (Exception ex) {
/** 此 Activity 加入黑名單。下次就不會(huì)再進(jìn)行處理。比如:Activity中沒有使用 @Autowired 注解,
結(jié)果卻使用了 ARouter.getInstance().inject(this); 這樣一來,在加載生成的輔助類的時(shí)候發(fā)現(xiàn)失敗,
以后就會(huì)進(jìn)入到黑名單,不會(huì)再理會(huì)inject這個(gè)行為了。
**/
blackList.add(className); // This instance need not autowired.
}
}
}
至此,一次完整的 Activity 屬性被自動(dòng)注入的過程分析完成。如果之前對(duì)ButterKnife了解的,看這些應(yīng)該很容易。