註解這東西雖然在jdk1.5就加進來了,但他的存在仍是由於使用Afinal框架的view注入才知道的。一直以爲注入特神奇,加了一句就能夠把對應view生成了。html
下面咱們來認識一下註解這個東西java
1、註解相關知識git
註解至關於一種標記,在javac編譯器,開發工具和其餘程序能夠用反射來了解你的類及各類元素上有無何種標記,看你有什麼標記,就去幹相應的事。標記能夠加在包,類,字段,方法,方法的參數以及局部變量上。github
一、元註解:做用是負責註解其餘註解。Java5.0定義了4個標準的meta-annotation類型,它們被用來提供對其它 annotation類型做說明數組
@Target:用於描述註解的使用範圍(即:被描述的註解能夠用在什麼地方)框架
ElementType參數有:ide
1)CONSTRUCTOR:用於描述構造器工具
2)FIELD:用於描述域佈局
3)LOCAL_VARIABLE:用於描述局部變量
4)METHOD:用於描述方法 開發工具
5)PACKAGE:用於描述包
6)PARAMETER:用於描述參數
7)TYPE:用於描述類、接口(包括註解類型) 或enum聲明
@Retention:用於描述註解的生命週期(即:被描述的註解在什麼範圍內有效)
RetentionPoicy參數有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在運行時有效(即運行時保留)
@Documented 代表這個註解被javadoc工具記錄,默認是不被javadoc註解的. 即聲明註解@Documented,則註解類型信息會被生成在文檔中
@Inherited指明被註解的類會自動繼承,即:註解類中的全部屬性與方法會被子類繼承
2、自定義註解
語法:public @interface 註解名 {定義體}
註解方法參數要求:
1)只能用public或默認(default)這兩個訪問權修飾
2)參數成員只能用基本類型byte,short,char,int,long,float,double,boolean八種基本數據類型和 String,Enum,Class,annotations等數據類型,以及這一些類型的數組.
3)若是隻有一個參數成員,最好把參數名稱設爲"value"
4)註解元素必須有肯定的值。能夠在定義註解的默認值中指定,或在使用註解時指定。如:String onClick() default "";
代碼以下:
定義註解
1 @Target(ElementType.FIELD) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 public @interface FindViewByIdAnnotation { 5 6 int id() default 0; 7 String onClick() default ""; 8 9 }
使用註解
1 @FindContentViewAnnotation(R.layout.activity_annotation) 2 public class AnnotationActivity extends Activity { 3 4 @FindViewByIdAnnotation(id = R.id.tvShow, onClick = "onClickShow") 5 private TextView tvShow; 6 7 @FindViewByIdAnnotation(id = R.id.tvHello, onClick = "onClickHello") 8 private TextView tvHello; 9 10 @Override 11 protected void onCreate(Bundle savedInstanceState) { 12 super.onCreate(savedInstanceState); 13 FindViewUtil.initView(this); 14 } 15 16 public void onClickShow() { 17 Toast.makeText(getApplicationContext(), "show Mr-Mo", Toast.LENGTH_SHORT).show(); 18 } 19 public void onClickHello() { 20 Toast.makeText(getApplicationContext(), "hello Mr-Mo", Toast.LENGTH_SHORT).show(); 21 } 22 }
3、註解處理器
註解若是不寫註解處理器基本至關於註釋。因此通常都會寫一個註解處理器。FindViewUtil:
1 public class FindViewUtil { 2 3 private FindViewUtil() { 4 } 5 6 public static void initView(Object object) { 7 initContentView(object); 8 initComponentView(object); 9 } 10 11 /** 12 * 初始化setContentView資源佈局 13 * 14 * @param object 15 */ 16 private static void initContentView(Object object) { 17 Class clazz = object.getClass(); 18 FindContentViewAnnotation contentView = (FindContentViewAnnotation) clazz.getAnnotation(FindContentViewAnnotation.class); 19 if (contentView != null) { 20 try { 21 int resId = contentView.value(); 22 // activity.setContentView(resId); 23 Method setContentViewMethod = clazz.getMethod("setContentView", int.class); 24 setContentViewMethod.invoke(object, resId); 25 26 } catch (Exception e) { 27 e.printStackTrace(); 28 } 29 } 30 } 31 32 /** 33 * 初始化控件 34 * 35 * @param object 36 */ 37 private static void initComponentView(final Object object) { 38 try { 39 final Class clazz = object.getClass(); 40 Field[] fields = clazz.getDeclaredFields(); 41 for (Field field : fields) { 42 FindViewByIdAnnotation viewByIdAnnotation = field.getAnnotation(FindViewByIdAnnotation.class); 43 if (viewByIdAnnotation != null) { 44 int resId = viewByIdAnnotation.id(); 45 final String onClick = viewByIdAnnotation.onClick(); 46 Object view; 47 if (object instanceof Fragment) { 48 Method getViewMethod = clazz.getMethod("getView"); 49 View rootView = (View) getViewMethod.invoke(object); 50 view = rootView.findViewById(resId); 51 } else { 52 Method findViewByIdMethod = clazz.getMethod("findViewById", int.class); 53 view = findViewByIdMethod.invoke(object, resId); 54 } 55 56 field.setAccessible(true); 57 field.set(object, view); 58 59 if (onClick != null && onClick.trim().length() > 0) { 60 Object objectField = field.get(object); 61 if (objectField instanceof View) { 62 final Method onClickMethod = clazz.getMethod(onClick); 63 View viewItem = (View) objectField; 64 viewItem.setOnClickListener(new View.OnClickListener() { 65 @Override 66 public void onClick(View v) { 67 try { 68 onClickMethod.setAccessible(true); 69 onClickMethod.invoke(object); 70 } catch (Exception e) { 71 e.printStackTrace(); 72 } 73 } 74 }); 75 } 76 } 77 } 78 } 79 } catch (Exception e) { 80 e.printStackTrace(); 81 } 82 } 83 84 }
到此就是自定義註解的所有步驟,以上代碼能夠完成view注入功能。
本文部分知識總結自:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html
代碼下載地址:https://github.com/MrxMo/IOCView