天天看點

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) {// 存在,不為空
			// 注解的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;
		}
	}

}
           

代碼寫完了,效果圖如下:

Android注解IOC架構【ViewInject】(一)

demo位址 點選下載下傳demo

感謝:http://blog.csdn.net/lmj623565791/article/details/39269193