1. 程式人生 > >android ViewId自動註解使用詳解(ViewInject)

android ViewId自動註解使用詳解(ViewInject)

Annotation就是註解了,JDK1.5新增加功能,該功能可用於類,構造方法,成員變數,方法,引數等的宣告中。

api版本23下,android studio裡是直接可以使用的,不用新增依賴庫,以前的api可能需要。下邊介紹幾種我覺得比較好用的註解。

NoNull註解

先看下原始碼
@Documented
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD})
public @interface NonNull {
}

@Retention(CLASS)指@NoNull編譯到類檔案裡
@Target({METHOD, PARAMETER, FIELD})指應用於方法,引數和成員變數

再看具體使用

其中區域性變數b 設定@NonNull是報錯的 因為原始碼指明並不能應用於區域性變數

  @NonNull  void testNonNull(@NonNull String a){
        @NonNull String b;
    }
    @NonNull String c;

CallSuper註解

首先還是先看原始碼

@Documented
@Retention(CLASS)
@Target({METHOD})
public @interface CallSuper {
}
標籤說明: 編譯時生效,應用於方法。下邊一起看下原始碼說明
/**
 * Denotes that any overriding methods should invoke this method as well.
 * <p>
 * Example:
 * <pre><code>
 *  @CallSuper
 *  public abstract void onFocusLost();
 * </code></pre>
 */

意指所有重寫方法都需要呼叫super.method();

ViewId註解

看了一圈發現google並沒有提供替換findViewById的註解方法,這裡再介紹一下如何自定義註解方法。
首先效仿原始碼,建立註解類
@Target(ElementType.FIELD)//表示用在成員變數
@Retention(RetentionPolicy.RUNTIME)//表示在生命週期是執行時生效
public @interface ViewInject {
    int value() default -1;//需要提供欄位獲取id值
}

核心邏輯就是定義註解介面,在特定時間,特定情況下執行我們預先寫好的註解方法,已到達我們想要的效果。

註解執行方法

  /** 
     * 解析註解 
     */  
    public void autoInjectAllField() {  
        try {  
            Class<?> clazz = this.getClass();  
            Field[] fields = clazz.getDeclaredFields();//獲得Activity中宣告的欄位  
            for (Field field : fields) {  
                // 檢視這個欄位是否有我們自定義的註解類標誌的  
                if (field.isAnnotationPresent(ViewInject.class)) {  
                    ViewInject inject = field.getAnnotation(ViewInject.class);  
                    int id = inject.value();  
                    if (id > 0) {  
                        field.setAccessible(true);  
                        field.set(this, this.findViewById(id));//給我們要找的欄位設定值  
                    }  
                }  
            }  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (IllegalArgumentException e) {  
            e.printStackTrace();  
        }  
    }  

呼叫此方法時,要先初始化xml檔案。所以在介面Activity中,必須在setContentView()執行後,才能呼叫父類的註解方法autoInjectAllField()

    @ViewInject(value=R.id.weightSum)
    Button a;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        autoInjectAllField();
        a.setText("成功");
    }