標籤:android ioc 架構 註解 viewinject
你還在為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) {// 存在,不為空白// 註解的IDint 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 blocke.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的Idint 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 blocke.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;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 注入布局和控制項ViewInjectUtils.inject(MainActivity.this);//設定onClick事件bt1.setOnClickListener(MainActivity.this);bt2.setOnClickListener(MainActivity.this);}@Overridepublic 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;}@Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch (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
Android註解IOC架構【ViewInject】(一)