你還在為setContentView()煩惱嗎?
或者說,你還在為findViewById()煩惱嗎?
如果是,請往下看...
IOC我們都知道,控制反轉(Inversion of Control) 就是項目分層 具體理論概述個人去查資料...
之前聽‘前輩’提過注解,但那會兒不知道是神馬,隻知道聽起來很神奇,因為‘前輩說’:不用去寫什麼setContentView和findViewById之類的代碼了,尤其是findViewById,想必大家都是深有體會,如果一個界面有十個view,就會有十行的findViewById...現在,有了注解之後,不需要了 一行搞定!
首先,我們需要兩個注解檔案:
ContentView.java:
package com.yx.viewinject_demo.ui;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/***
*
* 此類描述的是: ContentView用于在類上使用,主要用于标明該Activity需要使用的布局檔案
*
* @author: CS YX
* @version:1.0
* @date:2014-10-14 上午9:55:03
*/
@Target(ElementType.TYPE)
/*
* @Target表示該注解可以用于什麼地方,可能的類型TYPE(類),FIELD(成員變量)
* 可能的類型:TYPE、FIELD、METHOD、PARAMETER、CONSTRUCTOR
* 、LOCAL_VARIABLE、ANNOTATION_TYPE、PACKAGE
*/
@Retention(RetentionPolicy.RUNTIME)
/* @Retention表示:表示需要在什麼級别儲存該注解資訊;我們這裡設定為運作時。 可能的類型:SOURCE、CLASS、RUNTIME */
public @interface ContentView {
int value();
}
這個注解檔案是用于注入布局的,放在Activity類前面,标明該Activity引用的布局:
@ContentView(value = R.layout.activity_main)
public class MainActivity extends Activity
然後是第二個注解檔案:
ViewInject.java
package com.yx.viewinject_demo.ui;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/***
*
* 此類描述的是: 在成員變量上使用,用于指定View的Id
*
* @author: CS YX
* @version:1.0
* @date:2014-10-14 上午9:57:21
*/
@Target(ElementType.FIELD)
/*
* @Target表示該注解可以用于什麼地方,可能的類型TYPE(類),FIELD(成員變量)
* 可能的類型:TYPE、FIELD、METHOD、PARAMETER、CONSTRUCTOR
* 、LOCAL_VARIABLE、ANNOTATION_TYPE、PACKAGE
*/
@Retention(RetentionPolicy.RUNTIME)
/* @Retention表示:表示需要在什麼級别儲存該注解資訊;我們這裡設定為運作時。 可能的類型:SOURCE、CLASS、RUNTIME */
public @interface ViewInject {
int value();
}
這個注解檔案是用于注入View控件,用于指定View的Id
@ViewInject(R.id.bt1)
private Button bt1;
@ViewInject(R.id.bt2)
private Button bt2;
現在,我們需要定義一個ViewInject幫助類,這是核心類。
ViewInjectUtils.java:
package com.yx.viewinject_demo.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.yx.viewinject_demo.ui.ContentView;
import com.yx.viewinject_demo.ui.ViewInject;
import android.app.Activity;
/***
*
* 此類描述的是: 注解幫助類
*
* @author: CS YX
* @version:1.0
* @date:2014-10-14 上午10:09:35
*/
public class ViewInjectUtils {
private static final String METHOD_SET_CONTENTVIEW = "setContentView";
private static final String METHOD_FIND_VIEW_BY_ID = "findViewById";
/**
*
* 此方法描述的是: 注入布局和view控件
*
* @param activity
* Activity對象
*/
public static void inject(Activity activity) {
// 注入布局檔案
injectContentView(activity);
// 注入所有View控件
injectViews(activity);
}
/***
*
* 此方法描述的是: 注入布局檔案
*
* @param activity
* Activity對象
*/
private static void injectContentView(Activity activity) {
Class<? extends Activity> clazz = activity.getClass();
// 查詢類上是否有注解
ContentView contentView = clazz.getAnnotation(ContentView.class);
if (contentView != null) {// 存在,不為空
// 注解的ID
int contentViewLayoutId = contentView.value();
try {
// 獲得Method對象
Method method = clazz.getMethod(METHOD_SET_CONTENTVIEW,
int.class);
// 設定屬性可通路(私有)
method.setAccessible(true);
method.invoke(activity, contentViewLayoutId);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
*
* 此方法描述的是: 注入所有控件
*
* @param activity
* Activity對象
*/
private static void injectViews(Activity activity) {
// 獲得類對象
Class<? extends Activity> clazz = activity.getClass();
// 獲得類對象的所有屬性(公、私)
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
ViewInject viewInject = field.getAnnotation(ViewInject.class);
if (viewInject != null) {
// 獲得view的Id
int viewInjectId = viewInject.value();
if (viewInjectId != -1) {
Method method;
try {
// 獲得Method對象
method = clazz.getMethod(METHOD_FIND_VIEW_BY_ID,
int.class);
Object resView = method.invoke(activity, viewInjectId);
// 設定屬性可通路(私有)
field.setAccessible(true);
field.set(activity, resView);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
代碼已經基本寫完了,隻剩最後一個MainActivity:
MainActivity.java:
package com.yx.viewinject_demo.ui;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.yx.viewinject_demo.R;
import com.yx.viewinject_demo.utils.ToastUtils;
import com.yx.viewinject_demo.utils.ViewInjectUtils;
/**
*
* 此類描述的是: 應用主界面
*
* @author: CS YX
* @version:1.0
* @date:2014-10-21 上午10:08:31
*/
@ContentView(value = R.layout.activity_main)
public class MainActivity extends Activity implements OnClickListener {
@ViewInject(R.id.bt1)
private Button bt1;
@ViewInject(R.id.bt2)
private Button bt2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 注入布局和控件
ViewInjectUtils.inject(MainActivity.this);
//設定onClick事件
bt1.setOnClickListener(MainActivity.this);
bt2.setOnClickListener(MainActivity.this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bt1:
ToastUtils.showShort(this, "Hi,this is bt1...");
break;
case R.id.bt2:
ToastUtils.showShort(this, "Hello,this is bt2...");
break;
default:
break;
}
}
}
代碼寫完了,效果圖如下:
demo位址 點選下載下傳demo
感謝:http://blog.csdn.net/lmj623565791/article/details/39269193