利用反射和注解手?jǐn)]一個(gè)Android依賴注入框架

前言

本文是系列文章的第三篇,利用前兩篇的反射注解來(lái)手?jǐn)]一個(gè)Android依賴注入框架,還沒(méi)有學(xué)習(xí)過(guò)前兩篇文章內(nèi)容的小伙伴,抓緊學(xué)習(xí)一下吧。

創(chuàng)建注解

這里我們以Butterknife的ViewBind和OnClick為例,創(chuàng)建這么兩個(gè)注解,直接上代碼

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ViewBind {
    int value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnClick {
    int value();
}

這里沒(méi)有什么特別要說(shuō),這兩個(gè)注解需要用反射來(lái)解析,所以生命周期都要保留到RUNTIME(運(yùn)行時(shí)),一個(gè)需要作用到成員變量上,一個(gè)作用到方法上。

創(chuàng)建注解解析器

光有了注解還不行,必須要有與之對(duì)應(yīng)的注解解析器來(lái)解析注解,這里我們利用反射,直接上代碼

public class ViewInjust {

    public static void bind(Activity activity){
        bindView(activity);
        bindClick(activity);
    }

    private static void bindView(Activity activity) {
        Class<? extends Activity> aClass = activity.getClass();//拿到class類對(duì)象
        Field[] declaredFields = aClass.getDeclaredFields();//拿到所有的成員變量
        for (Field field:declaredFields) {//遍歷成員變量
            if (field.isAnnotationPresent(ViewBind.class)) {//判斷該變量是否被注解
                ViewBind annotation = field.getAnnotation(ViewBind.class);//獲得ViewBind
                int viewId = annotation.value();//拿到viewId
                View view = activity.findViewById(viewId);//拿到view
                try {
                    field.setAccessible(true);//取消安全檢查機(jī)制
                    field.set(activity,view);//把view賦值給當(dāng)前成員變量
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void bindClick(final Activity activity) {
        Class<? extends Activity> aClass = activity.getClass();//拿到class類對(duì)象
        Method[] declaredMethods = aClass.getDeclaredMethods();//拿到所有的方法
        for (final Method method:declaredMethods) {//遍歷所有的方法
            if (method.isAnnotationPresent(OnClick.class)) {
                OnClick annotation = method.getAnnotation(OnClick.class);//獲得Onclick注解
                int viewId = annotation.value();
                View view = activity.findViewById(viewId);
                view.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        try {
                            method.setAccessible(true);//取消安全檢查機(jī)制
                            method.invoke(activity,null);//調(diào)用對(duì)應(yīng)的方法
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        }
    }
}

代碼上面都有充分的注釋,主要運(yùn)用就是我們?cè)诘谝黄袑W(xué)到的反射的知識(shí)。

測(cè)試一下

public class MainActivity extends AppCompatActivity {

    @ViewBind(R.id.textView)
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewInjust.bind(this);
        textView.setText("測(cè)試綁定");
    }

    @OnClick(R.id.button)
    private void clickBtn(){
        Toast.makeText(getApplicationContext(),"點(diǎn)擊了按鈕",Toast.LENGTH_SHORT).show();
    }
}

測(cè)試結(jié)果


測(cè)試結(jié)果.jpg

總結(jié)

這篇文章是我寫過(guò)的文章中最簡(jiǎn)單、內(nèi)容最少的一篇,我原本不想寫來(lái)著,但是作為一個(gè)系列文章,還是有必要把前面兩篇文章的內(nèi)容串起來(lái)一下并鞏固一番。但是你以為Butterknife就是像本文的實(shí)現(xiàn)那么簡(jiǎn)單嗎?當(dāng)然不是,之前也有提到過(guò)反射的性能會(huì)比較差,這樣大規(guī)模且頻繁地使用就會(huì)更差,所以Butterknife用了一個(gè)更加高深的方式。我將在下一篇文章中為大家詳解Butterknife并親自手?jǐn)]一個(gè)出來(lái),敬請(qǐ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ù)。

相關(guān)閱讀更多精彩內(nèi)容

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