或者说,你还在为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