你还在为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
时间: 2024-10-15 08:01:04