最近看開源代碼,發現有這麼一句:
@ViewInject(id = R.id.mIvGRZX,click = true)
private ImageView mIvGRZX;
就來調查下相關的技術原理。
不用慌, 它就等同於: findViewById
IOC框架
Inversion of Control,英文縮寫爲IOC,字面翻譯:控制反轉。
就是一個類裏面需要用到很多個成員變量,傳統的寫法,你要用這些成員變量,那麼你就new 出來用唄!
IOC的原則是:NO,我們不要new,這樣耦合度太高,你配置個xml文件,裏面標明哪個類,裏面用了哪些成員變量,等待加載這個類的時候,我幫你注入(new)進去;當然了,你又會覺得,寫個配置文件,臥槽,這多麻煩。
於是乎,又出現了另一種方案,得你嫌配置文件麻煩,那用註解唄在你需要注入的成員變量上面加個註解,例如:@Inject,這樣就行了,你總不能說這麼個單詞麻煩吧。當然了,有了配置文件和註解,那麼怎麼注入呢?其實就是把字符串類路徑變成類麼,這個時候需要用到反射。
反射不在多說,java代碼比較普遍的技術。
註解
JAVA中的註解是一種繼承自接口java.lang.annotation.Annotation的特殊接口。
簡單來說就是JAVA通過動態代理的方式爲你生成了一個實現了接口Annotation的實例,然後對該代理實例的屬性賦值,這樣就可以在程序運行時通過反射獲取到註解的配置信息。
註解類似於一種標記,在程序中加了註解就等於爲程序打上了某種標記。
程序可以利用JAVA的反射機制來了解你的類及各種元素上有無何種標記,針對不同的標記,就去做相應的事件。標記可以加在包,類,方法,方法的參數以及成員變量上。
Annotation
Java 註解(Annotation)又稱 Java 標註,是 JDK5.0 引入的一種註釋機制。
Java 語言中的類、方法、變量、參數和包等都可以被標註。和 Javadoc 不同,Java 標註可以通過反射獲取標註內容。在編譯器生成類文件時,標註可以被嵌入到字節碼中。
Java 虛擬機可以保留標註內容,在運行時可以獲取到標註內容 。 當然它也支持自定義 Java 標註。
創建註解類
添加代碼:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value();
}
@Target表示註解可以用於什麼地方,這裏用於類,其他參數如:FILED(成員),METHOD(方法),PACKAGE(包),ANNOTATION_TYPE(註解的註解),CONSTRUCTOR(構造函數),PARAMETER(參數),LOCAL_VARIABLE(局部變更)
@Retention什麼時候加載註解類,一般都是RetentionPolicy.RUNTIME運行的時候。
創建注入工具類
InjectUtils.class:
public class InjectUtils {
public static final String ACTIVITY_MAIN_CONTENTVIEW="setContentView";
/**
* 注入所有
* @param activity
*/
public static void injectAll(Activity activity){
injectContentView(activity);
}
/**
* 注入ContentView
* @param activity
*/
public static void injectContentView(Activity activity){
Class<? extends Activity> clazz = activity.getClass();//獲取該類信息
ContentView contentView = clazz.getAnnotation(ContentView.class);//獲取該類ContentView的註解
//如果有註解
if(contentView!=null){
int viewId=contentView.value();//獲取註解類參數
try {
Method method=clazz.getMethod(ACTIVITY_MAIN_CONTENTVIEW,int.class);//獲取該方法的信息
method.setAccessible(true);//獲取該方法的訪問權限
method.invoke(activity,viewId);//調用該方法的,並設置該方法參數
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
這樣就關聯起來了。