IOC注解開發(fā)

1.什么是注解開發(fā)望伦?

控制反轉(zhuǎn)(Inversion of Control):減少大量重復代碼的書寫。如ButterKnife,xUtils...

2.效果預覽

3.怎樣進行注解開發(fā)(屬性注解開發(fā)為例)?

3.1 創(chuàng)建Annotation

//注解使用時所在的地方  ElementType.FIELD -> 方法上面  ElementType.METHOD -> 屬性上面ElementType.TYPE -> 類上面
@Target(ElementType.FIELD)
//檢查的時間  RetentionPolicy.SOURCE  -> 編碼時(如override)   RetentionPolicy.RUNTIME  -> 運行時   RetentionPolicy.CLASS  -> 編譯時
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewById {
    //@ViewById(R.id.tv_test)  當注解的屬性只有一個時隙疚,可以命名為 value姆另,這樣在使用時可以使用快捷方式 – 直接傳入值,而不是聲明屬性名
    int value();
}

3.2 創(chuàng)建類實現(xiàn)注解內(nèi)部邏輯

public class ViewUtils {
   public static void inject(Activity activity) {  
          //傳兩個相同的參數(shù)鸣戴?意思不一樣哦
          injectField(activity, activity);
    }
}
/**
 * 屬性注解
 * @param activity  用于尋找目標控件
 * @param object  用于反射的類
 */
private static void injectField(Activity activity, Object object) {
    //1.找到所有的屬性
    Field[] fields = object.getClass().getDeclaredFields();
    //2.找到ViewById注解所在的屬性
    for (Field field : fields) {
        ViewById fieldAnnotation = field.getAnnotation(ViewById.class);
        //如果屬性存在
        if (fieldAnnotation != null) {
            //3.通過注解屬性中的value值找到對應的控件
            int resId = fieldAnnotation.value();
            View view = activity.findViewById(resId);
            //如果id對應的控件存在
            if (view != null) {
                //可以調(diào)用屬性的私有方法
                field.setAccessible(true);
                try {
                    //4.調(diào)用field的set方法重新賦值
                    field.set(object, view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.3 在activity中使用

    @ViewById(R.id.tv_test)
    private TextView textView;
   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewUtils.inject(this);
    }
  textView.setText("woochen123");

4.和效果圖不一樣?那在補充一點吧

@OnClick注解核心代碼:

   /**
     * 點擊事件注解
     * @param activity
     * @param object
     */
    private static void injectMethod(Activity activity, Object object) {
        //1.找到所在類所有的方法
        Method[] methods = object.getClass().getDeclaredMethods();
        //2.找到含有注解Onclick的方法
        for (Method method : methods) {
            OnClick methodAnnotation = method.getAnnotation(OnClick.class);
            if(methodAnnotation != null){
                //如果方法存在
                //3.拿到其中的value值粘拾,并找到相應的控件
                int[] resIds = methodAnnotation.value();
                for (int resId : resIds) {
                    View view = activity.findViewById(resId);
                    if(view != null){
                        //如果id對應的控件存在窄锅,調(diào)用onClickListener
                        view.setOnClickListener(new DeclaredClickListener(object,method));
                    }
                }
            }
        }
    }
    /**
     * 自定義點擊事件監(jiān)聽器
     */
    private static class DeclaredClickListener implements View.OnClickListener {
        private  Method mMethod;
        private  Object mObject;

        public DeclaredClickListener(Object object, Method method) {
            mMethod = method;
            mObject = object;
        }

        @Override
        public void onClick(View v) {
            try {
                //可以調(diào)用私有方法
                mMethod.setAccessible(true);
                //默認調(diào)用一個參數(shù)
                mMethod.invoke(mObject,v);
            } catch (Exception e) {
                try {
                    //如果拋出異常調(diào)用無參數(shù)的方法
                    mMethod.invoke(mObject,null);
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }
        }

5.知識點補充

5.1元注解:修飾其他的注解

@Documented:讓注解信息出現(xiàn)在 document 中
@Retention : 指出注解如何存儲,支持以下三種參數(shù)

  • RetentionPolicy.SOURCE : 注解只保留在源碼中缰雇,編譯時會忽略
  • RetentionPolicy.CLASS : 更高一級入偷,編譯時被編譯器保留,但是運行時會被 JVM 忽略
  • RetentionPolicy.RUNTIME : 最高級械哟,運行時會被保留疏之,可以被運行時訪問
    @Target :指出注解作用于(修飾)什么對象,支持以下幾種參數(shù)
  • ElementType.TYPE : 作用于任何類暇咆、接口锋爪、枚舉
  • ElementType.FIELD : 作用于一個域或者屬性
  • ElementType.METHOD : 作用于一個方法
  • ElementType.PARAMTER : 作用于參數(shù)
  • ElementType.CONSTRUCTOR : 作用于構(gòu)造函數(shù)
  • ElementType.LOCAL_VARIABLE : 作用于本地變量
  • ElementType. ANNOTATION_TYPE : 作用于注解
  • ElementType.PACKAGE : 作用于包
    @Inherited :當前注解是否可以繼承

5.2注解的特點:

  • 形式上和接口很像,都是定義方法爸业,但是區(qū)別在于注解中定義的方法實質(zhì)上是屬性其骄,而返回值是指屬性的類型
  • 可以給定義的注解方法賦上默認的值
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Author {
    String name() default "woochen123";
    String date();
}

5.3注解處理器的類型

運行時處理器
編譯時處理器

6.再說一句

本例中的代碼,是從項目中簡化后提出的扯旷,可能有些地方顯得多余拯爽,可能有些邏輯不夠完善。意思應該是表達出來了(伸手黨就沒辦法咯-_-!)

7.小結(jié)

本例的原理是利用反射+運行時檢查來實現(xiàn)的注解钧忽,原理與xutils的view注入相同毯炮。還有一種是編譯時檢查,ButterKnife是比較有代表性的惰瓜, 它的實現(xiàn)是通過字節(jié)流在本地生成相關(guān)文件否副。前者由于用到反射,會在一定程度上消耗性能(相比視圖的渲染崎坊,就是微不足道了)备禀;后者會將生成的文件打包進apk中,在一定程度上增加apk的體積(相比巨大的三方庫的引入,這也算不上什么啦)曲尸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赋续,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子另患,更是在濱河造成了極大的恐慌纽乱,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昆箕,死亡現(xiàn)場離奇詭異鸦列,居然都是意外死亡,警方通過查閱死者的電腦和手機鹏倘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門薯嗤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人纤泵,你說我怎么就攤上這事骆姐。” “怎么了捏题?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵玻褪,是天一觀的道長。 經(jīng)常有香客問我公荧,道長带射,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任稚矿,我火速辦了婚禮庸诱,結(jié)果婚禮上捻浦,老公的妹妹穿的比我還像新娘晤揣。我一直安慰自己,他們只是感情好朱灿,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布昧识。 她就那樣靜靜地躺著,像睡著了一般盗扒。 火紅的嫁衣襯著肌膚如雪跪楞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天侣灶,我揣著相機與錄音甸祭,去河邊找鬼。 笑死褥影,一個胖子當著我的面吹牛池户,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼校焦,長吁一口氣:“原來是場噩夢啊……” “哼赊抖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寨典,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤氛雪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后耸成,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體报亩,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年井氢,在試婚紗的時候發(fā)現(xiàn)自己被綠了捆昏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡毙沾,死狀恐怖骗卜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情左胞,我是刑警寧澤寇仓,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站烤宙,受9級特大地震影響遍烦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜躺枕,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一服猪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拐云,春花似錦罢猪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至薇缅,卻和暖如春危彩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泳桦。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工汤徽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人灸撰。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓谒府,卻偏偏與公主長得像漆羔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子狱掂,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內(nèi)容