自定OnClickListener注解,减少点击事件监听器的代码
2016-10-17 23:53
363 查看
在上一篇文章 “自定的FindViewById注解,实现同名的R.id无需初始化”中讲到了自定用FindViewById减少部分相同的代码书写,实际开发过程发现,点击事件的监听器的注册(OnClickListener)也是同样要写许多相同的代码,所以再开发了一个新的注解@OnClickListener,来减少这部分代码的书写,毕竟偷懒才是程序员进步的源泉嘛!
这个注解目前支持注解在View上,也支持注解在方法上,实现方法还是和上一篇文章一样使用自己写的BaseActivity去解析,直接看代码吧
OnClickListener注解
实现解析注解的BaseActivity
真正的Activity的使用(布局文件就不写了,就只是4个按钮而且)
这个注解目前支持注解在View上,也支持注解在方法上,实现方法还是和上一篇文章一样使用自己写的BaseActivity去解析,直接看代码吧
OnClickListener注解
package onclick.kazz.com.onclick; import android.view.View; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by Kazz on 2016/10/9.<br/> * 把这个注解在view上,可以给一个view指定一个OnClickListener<br/> * value值是这个view的OnClickListener的方法名,<br/> * 如果不填值,则会解析方法名,如果方法名是“view名+_OnClickListener”,则会给该view注册监听器<br/> * * @serial modify by Kazz 2016-10-10 新增方法级别的注解,使得这个注解支持注解到方法上,修改后方法级别的注解优先级高于属性级别的注解 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.METHOD}) public @interface OnClickListener { public final String DEFAULT_VALUE = "123cnicd93jkdji20irojkjfio"; /** * 需要指定的OnClickListener的处理方法名,可为空,空的时候将会指定“view变量名+_OnClickListener” * @return */ String value() default DEFAULT_VALUE; }
实现解析注解的BaseActivity
package onclick.kazz.com.onclick; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Toast; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * Created by Kazz on 2016/10/17. */ public abstract class BaseActivity extends AppCompatActivity { final String CURRENT_TAG = "BaseActivity"; abstract protected int setLayoutId(); abstract protected void initUI(); @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(setLayoutId()); initUI(); initOnclickAnno(); } /** * 初始化含有OnClickListener的注解 */ private void initOnclickAnno() { //反射遍历所有的属性 for (Field field : getClass().getDeclaredFields()) { try { field.setAccessible(true); final String fieldName = field.getName(); if (field.isAnnotationPresent(OnClickListener.class)) { OnClickListener anno = field.getAnnotation(OnClickListener.class); String methodName = anno.value(); View view = (View) field.get(BaseActivity.this); if (methodName.equals(OnClickListener.DEFAULT_VALUE)) { methodName = fieldName + "_OnClickListener"; } try { final Method method = getClass().getDeclaredMethod(methodName, View.class); //尝试获取该方法,如果找不到,则会抛出NoSuchMethodException final String methodNamee = methodName; method.setAccessible(true); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { method.invoke(BaseActivity.this, v); //通过发射执行此方法 } catch (Exception e) { Log.e(CURRENT_TAG, "initOnClickListenerAnnotation:调用" + methodNamee + "{}出错"); } } }); } catch (NoSuchMethodException e) { Log.e(CURRENT_TAG, "initOnClickListenerAnnotation:" + fieldName + "属性没有找到相应的默认OnClickListener!!!"); continue; } } } catch (Exception e) { Log.e(CURRENT_TAG, "initOnClickListenerAnnotation异常"); } } //反射遍历所有的方法 for (final Method method : getClass().getDeclaredMethods()) { method.setAccessible(true); if (method.isAnnotationPresent(OnClickListener.class)) { OnClickListener anno = method.getAnnotation(OnClickListener.class); String viewName = anno.value(); final String methodName = method.getName(); if (OnClickListener.DEFAULT_VALUE.equals(viewName)) { try { viewName = methodName.split("_OnClickListener")[0]; //尝试识别出view的变量名 Log.i(CURRENT_TAG, "initOnClickListenerAnnotation:方法" + methodName + "注解的view变量名是默认的,将自动识别为" + viewName); } catch (Exception e) { Log.e(CURRENT_TAG, "initOnClickListenerAnnotation:方法"+methodName+"拆分默认的view变量名出错"); continue; } } try { Field field = getClass().getDeclaredField(viewName); field.setAccessible(true); View view = (View) field.get(BaseActivity.this); final String methodNamee = methodName; view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { method.invoke(BaseActivity.this, v); } catch (Exception e) { Log.e(CURRENT_TAG, "initOnClickListenerAnnotation:"+methodNamee+"被调用时出错" ); } } }); } catch (NoSuchFieldException e) { Log.e(CURRENT_TAG, "initOnClickListenerAnnotation:未找到"+methodName+"方法中注解的view变量名"+viewName); } catch (Exception e) { Log.e(CURRENT_TAG, "initOnClickListenerAnnotation:方法"+methodName+"为"+viewName+"添加点击事件出错"); } } } } protected void showToast(String msg) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); } }
真正的Activity的使用(布局文件就不写了,就只是4个按钮而且)
package onclick.kazz.com.onclick; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends BaseActivity { @OnClickListener("bt_1OnClickListner1234abcd") private Button bt_1; @OnClickListener private Button bt_2; private Button bt_3; private Button bt_4; @Override protected int setLayoutId() { return R.layout.activity_main; } @Override protected void initUI() { bt_1 = (Button)findViewById(R.id.bt_1); bt_2 = (Button)findViewById(R.id.bt_2); bt_3 = (Button)findViewById(R.id.bt_3); bt_4 = (Button)findViewById(R.id.bt_4); } private void bt_1OnClickListner1234abcd(View view){ showToast("点击了按钮1"); } private void bt_2_OnClickListener(View view){ showToast("点击了按钮2"); } @OnClickListener("bt_3") private void bt_3_OnClickListnerabcd1234(View view){ showToast("点击了按钮3"); } @OnClickListener private void bt_4_OnClickListener(View view){ showToast("点击了按钮4"); } }
相关文章推荐
- Android中控件的onClickListener,点击监听器
- Java模拟Android View OnClickListener点击事件
- Volley, HttpUtils,省略findViewById()和点击事件的.setOnClickListener(this);,DbUtils
- TextView ClickableSpan onClickListener点击事件冲突
- Android中控件的onClickListener,点击监听器
- android view点击事件无效 OnClickListener
- RecyclerView设置点击监听器OnClickListener
- 点击TButton后的执行OnClick和OnMouseDown两个事件的过程(其实是通过WM_COMMAND执行程序员的代码)
- Volley, HttpUtils,省略findViewById()和点击事件的.setOnClickListener(this);,DbUtils
- 自定义点击事件OnClickListener内部监听外部回调adapter内的点击事件移到Activity
- Android开发 - 常用点击响应事件OnClickListener
- Hibernate拦截器(Interceptor)与事件监听器(Listener)
- 事件处理之二:点击事件监听器的五种写法
- 控件设置为focusable为true后要点击第2下才能触发OnClick事件
- 点击button触发onclick事件判空后依旧自动跳转
- 【Android】技术调研:用代码模拟屏幕点击、触摸事件
- android开发中监听器的三种实现方法(OnClickListener)
- 在IE6、8中 <a>、button点击事件(onclick)没得反应经验总结
- Button 点击事件onclick实现的四种方式
- 【Unity】UGUI怎么动态的添加按钮的OnClick点击事件