ARouter系列二:@Autowired屬性注入

如果對(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)類是 AutowiredServiceImplAutowiredServiceImpl 封裝了對(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)該很容易。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容