Android 注解findViewById、onClick
来源:互联网 发布:chrome 插件 注入js 编辑:程序博客网 时间:2024/03/28 22:59
当在项目中一个页面有着太多的控件的时候,你是否被findViewById快折磨疯了,在listView列表类的findView折磨到不想写的冲动,那么在Java中利用反射和注解原理来就可以解决,当然这样在性能上多少有点欠缺,要丢失的是反应时间上的性能,毕竟要去扫描类中符合要求的字段和方法再去执行你自己定义的注解方法和字段赋值。什么事情都是一把双刃剑,你丢失了几毫秒的性能在代码上得到了开发的速度和代码的优美简洁,我自己看来在于自己怎么去选择。
阐述下用到的知识点:(1)要findViewById自己执行,就需要利用反射原理去执行类中的方法“findViewById(int id)”,那么id的值就靠注解字段来获取。
// 执行该方法,返回一个Object类型的View实例Object resView = method.invoke(object, id);field.setAccessible(true);// 把字段的值设置为该View的实例field.set(object, resView);
(2)对View设置onClick事件也是类似的,只是我们需要的是对方法进行注解,然后对找到的控件进行一一设置点击事件即可。Method findViewMethod = (view == null ? objectClass : view.getClass()).getMethod("findViewById", int.class);final View resView = (View) findViewMethod.invoke(object, id);if (resView == null) { Log.e(TAG, "@OnClick annotation value view id (index = "+index+") isn't find any view in "+object.getClass().getSimpleName()); return; } resView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { method.invoke(object, resView); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } });
1.定义控件对象注解字段类
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface ViewInject{ int value() default -1;}
2.定义OnClick事件的方法注解类
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface OnClick { int [] value();}3.定义注解工具类import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import android.util.Log;import android.view.View;/** * 注解工具类 * Annotation Utils */public class ViewUtils { private static final String TAG = "RRL"; /** * find view in activity * * @param object */ public static void inject(Object object) { long time = System.currentTimeMillis(); reflectFindView(object, null); injectMethod(object, null); Log.e(TAG, ViewUtils.class.getSimpleName() + " inject use time:" + (System.currentTimeMillis() - time) + "ms"); } /** * find view in fragment or ViewHolder * * @param object Fragment or ViewHolder * @param view there is findViewById method view */ public static void inject(Object object, View view) { long time = System.currentTimeMillis(); reflectFindView(object, view); injectMethod(object, view); Log.e(TAG, ViewUtils.class.getSimpleName() + " inject use time:" + (System.currentTimeMillis() - time) + "ms"); } /** * 反射找到View Id * Find view id by reflect * * @param object Activity Fragment or ViewHolder * @param view there is findViewById method view */ private static void reflectFindView(Object object, View view) { //Access to all of the fields Class<?> fieldClass = object.getClass(); Field[] fields = fieldClass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { //if every field have you defined annotation class(ViewInject.class) and get view id. Field field = fields[i]; ViewInject viewInject = field.getAnnotation(ViewInject.class); if (viewInject != null) {//if you defined annotation class's values is not null reflectFindView(object, view, field, viewInject.value()); } } } /** * 反射找控件 * find view by reflect class * * @param field annotation field * @param view findViewById class * @param id view's Id */ private static void reflectFindView(Object object, View view, Field field, int id) { if (id == -1) { return; } Class<?> fieldCls = object.getClass(); Class<?> findViewClass = (view == null ? object : view).getClass(); try { // 获取类中的findViewById方法,参数为int Method method = (findViewClass == null ? fieldCls : findViewClass).getMethod("findViewById", int.class); // 执行该方法,返回一个Object类型的View实例 Object resView = method.invoke(view == null ? object : view, id); field.setAccessible(true); // 把字段的值设置为该View的实例 field.set(object, resView); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } /** * Annotation method * * @param object annotation class with declared methods * @param view annotation view in Fragment or ViewHolder */ private static void injectMethod(Object object, View view) { long time = System.currentTimeMillis(); reflectMethod(object, view); Log.e(TAG, ViewUtils.class.getSimpleName() + " inject use time:" + (System.currentTimeMillis() - time) + "ms"); } /** * reflect method * * @param object annotation class with declared methods * @param view annotation view in Fragment or ViewHolder */ private static void reflectMethod(Object object, View view) { Class<?> objectClass = object.getClass(); Method[] objectMethods = objectClass.getDeclaredMethods(); for (int i = 0; i < objectMethods.length; i++) { Method method = objectMethods[i]; method.setAccessible(true);//if method is private //get annotation method OnClick onClick = method.getAnnotation(OnClick.class); if (onClick != null) { int[] values = onClick.value(); for (int index = 0; index < values.length; index++) { int id = values[index]; reflectMethod(object, view, id,index, method); } } } } /** * reflect method * * @param object annotation class with declared methods * @param view annotation view in Fragment or ViewHolder * @param id annotation view id * @param method annotation method */ private static void reflectMethod(final Object object, View view, int id,int index, final Method method) { Class<?> objectClass = object.getClass(); try { Method findViewMethod = (view == null ? objectClass : view.getClass()).getMethod("findViewById", int.class); final View resView = (View) findViewMethod.invoke(object, id); if (resView == null) { Log.e(TAG, "@OnClick annotation value view id (index = "+index+") isn't find any view in " + object.getClass().getSimpleName()); return; } resView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { method.invoke(object, resView); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }}
4.使用方法(1)在Activity中使用:
在定义的字段时候如下:
@ViewInject(R.id.tv_content) private TextView tv_content; //在onCreate()中setContentView()方法之后调用ViewUtils.inject(this);
(2)在Fragment中使用:
@ViewInject(R.id.tv_content) private TextView tv_content; @Override public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fgt_main, null); ViewUtils.inject(this, view); return view; }
(3)在ViewHolder中使用:
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = LayoutInflater.from(MainFgt.this.getContext()).inflate(R.layout.list_item_content, null); ViewUtils.inject(holder, convertView); convertView.setTag(holder); } else holder = (ViewHolder) convertView.getTag(); holder.tv_list_content.setText(position + "测试文字"); return convertView; } private class ViewHolder { @ViewInject(R.id.tv_list_content) private TextView tv_list_content; }
1 0
- Android 注解findViewById、onClick
- Android:注解初始化findViewById
- Android: 使用注解findViewById
- Android学习:onClick +findViewById+Toast基础
- Android中通过注解代替findViewById方法
- Android中通过注解代替findViewById方法
- android findviewbyid的简单注解实现
- Android中通过注解代替findViewById方法
- Android使用注解避免大量的findViewById()
- Android中通过注解代替findViewById方法
- android通过注解实现findViewById 和 setOnClickListener
- 通过JAVA注解简化android的findViewById
- Android中注解详解,通过注解代替findViewById方法
- android---------Android中通过注解代替findViewById方法
- Android中注解和反射的结合findViewById
- Android高效率编码-findViewById()的蜕变-注解,泛型,反射
- android 自动初始化控件 不用注解不用findViewByid
- Android 注解的简单使用之省去findViewById()
- Ubuntu 17.04更改鼠标移动速度
- 循环冗余校验 (CRC) 计算的C++ 代码
- Ubuntu16.04 + CUDA8.0 + CuDNN + OpenCV + caffe
- Java中包与包之间方法的调用及其关键字区分(基础)
- FFmpeg学习—解决ffmpeg 进行Audio 编码 采用AV_SAMPLE_FMT_S16 格式报 Input contains NaN/+-Inf 错误的问题
- Android 注解findViewById、onClick
- 重温Spring之旅7——Spring的事务管理
- Could not calculate build plan: Plugin org.apache.maven.plugins:maven-resources-plugin:2.6 or one of
- Tensorflow入门-实现神经网络
- Python进阶(四十)-数据可视化の使用matplotlib进行绘图
- Win10下使用WampServer搭建PHP开发环境
- UML的使用
- 鼠标(镜头)旋转控制
- lua语言总结