前言:
对于很多安卓开发者来说,防快速点击的实现,并不是一件难事。难的是,如何优雅的实现。现在,主流的做法,有自己在onClick方法的顶部加时间判断。也有通过,第三方注解框架去解决。但是,如果你既不想在onClick里面加,又不想用第三方框架,又想以最少的改动,来实现,咋办?干大事的人,都是直接上使用案例的,无Code,无JB。
Here is the code shows you How to use it:
// 这是findView的代码,但请注意,这不是findViewById,这是findClickView。Button btnTest = findClickView(R.id.btn_test);// 这是Activity的onClick方法。public void onClick(View view) {switch (view.getId()) {case R.id.btn_test:// todobreak;}}
就是这么简单,findClickView方法,会帮你setOnClickListener,并做防抖实现。让我们一起来看看findClickView的内部实现。
/*** Find出来的View,自带防抖功能*/public <T extends View> T findClickView(int id) {T view = (T) findViewById(id);view.setOnClickListener(new EventListener(this));return view;}
可以看到,这个方法,内部调用的,还是findViewById。不同的是,里面设置onClick的时候,传了一个EventListener的实例。而这个类,也是防抖的关键。废话不多说,直接看代码:
package com.laka.androidlib.listener;import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.AdapterView.OnItemSelectedListener;import java.lang.reflect.Method;/*** 防抖事件* 用法setOnClickListener(new EventListener(obj));* obj类,必须得有clickMethod(View)方法。默认是onClick(View)方法。*/
public class EventListener implements OnClickListener,OnLongClickListener, OnItemClickListener, OnItemSelectedListener,OnItemLongClickListener {private Object handler;// 点击事件的方法,默认是onClickprivate String clickMethod = "onClick";private String longClickMethod;private String itemClickMethod;private String itemSelectMethod;private String nothingSelectedMethod;private String itemLongClickMethod;// 间隔时间private final static int INTERVAL_TIME = 1000;public EventListener(Object handler) {this.handler = handler;}public EventListener click(String method){this.clickMethod = method;return this;}public EventListener longClick(String method){this.longClickMethod = method;return this;}public EventListener itemLongClick(String method){this.itemLongClickMethod = method;return this;}public EventListener itemClick(String method){this.itemClickMethod = method;return this;}public EventListener select(String method){this.itemSelectMethod = method;return this;}public EventListener noSelect(String method){this.nothingSelectedMethod = method;return this;}public boolean onLongClick(View v) {return invokeLongClickMethod(handler,longClickMethod,v);}public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {return invokeItemLongClickMethod(handler, itemLongClickMethod,arg0,arg1,arg2,arg3);}public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {invokeItemSelectMethod(handler,itemSelectMethod,arg0,arg1,arg2,arg3);}public void onNothingSelected(AdapterView<?> arg0) {invokeNoSelectMethod(handler,nothingSelectedMethod,arg0);}public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {invokeItemClickMethod(handler,itemClickMethod,arg0,arg1,arg2,arg3);}public void onClick(View v) {invokeClickMethod(handler, clickMethod, v);}//上一次点击时间static long lastclicktime=0;/*** 点击事件* @param handler* @param methodName* @param params* @return*/private static Object invokeClickMethod(Object handler, String methodName, Object... params){if(handler == null)return null;Method method = null;try{if(System.currentTimeMillis()-lastclicktime > INTERVAL_TIME){method = handler.getClass().getDeclaredMethod(methodName,View.class);Object result = method.invoke(handler, params);lastclicktime = System.currentTimeMillis();return result;}}catch(Exception e1){handlerException(e1);}return null;}public static void handlerException(Exception e){}/*** 长按事件* @param handler* @param methodName* @param params* @return*/private static boolean invokeLongClickMethod(Object handler, String methodName, Object... params){if(handler == null) return false;Method method = null;try{ //public boolean onLongClick(View v)method = handler.getClass().getDeclaredMethod(methodName,View.class);if(method!=null){Object obj = method.invoke(handler, params);return obj==null?false: Boolean.valueOf(obj.toString());}else{method = handler.getClass().getDeclaredMethod(methodName);if(method!=null){Object obj = method.invoke(handler);return obj==null?false: Boolean.valueOf(obj.toString());}elsethrow new RuntimeException("no such method:"+methodName);}}catch(Exception e){e.printStackTrace();}return false;}private static Object invokeItemClickMethod(Object handler, String methodName, Object... params){if(handler == null) return null;Method method = null;try{ method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class,View.class,int.class,long.class);if(method!=null){if(System.currentTimeMillis()-lastclicktime > INTERVAL_TIME){Object result= method.invoke(handler, params);lastclicktime= System.currentTimeMillis();return result;}}else{method = handler.getClass().getDeclaredMethod(methodName,int.class,long.class);if(method!=null){Object result= method.invoke(handler, params[2],params[3]);lastclicktime= System.currentTimeMillis();return result;}elsethrow new RuntimeException("no such method:"+methodName);}}catch(Exception e){e.printStackTrace();}return null;}private static boolean invokeItemLongClickMethod(Object handler, String methodName, Object... params){if(handler == null) throw new RuntimeException("invokeItemLongClickMethod: handler is null :");Method method = null;try{ ///onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,long arg3)method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class,View.class,int.class,long.class);if(method!=null){Object obj = method.invoke(handler, params);return Boolean.valueOf(obj==null?false: Boolean.valueOf(obj.toString()));}else{method = handler.getClass().getDeclaredMethod(methodName, int.class,long.class);if(method!=null){Object obj = method.invoke(handler,params[2],params[3]);return Boolean.valueOf(obj==null?false: Boolean.valueOf(obj.toString()));}elsethrow new RuntimeException("no such method:"+methodName);}}catch(Exception e){e.printStackTrace();}return false;}private static Object invokeItemSelectMethod(Object handler, String methodName, Object... params){if(handler == null) return null;Method method = null;try{ ///onItemSelected(AdapterView<?> arg0, View arg1, int arg2,long arg3)method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class,View.class,int.class,long.class);if(method!=null)return method.invoke(handler, params); elsethrow new RuntimeException("no such method:"+methodName);}catch(Exception e){e.printStackTrace();}return null;}private static Object invokeNoSelectMethod(Object handler, String methodName, Object... params){if(handler == null) return null;Method method = null;try{ //onNothingSelected(AdapterView<?> arg0)method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class);if(method!=null)return method.invoke(handler, params); elsethrow new RuntimeException("no such method:"+methodName);}catch(Exception e){e.printStackTrace();}return null;}}
代码,复制粘贴,即可用。0 warnings, 0 errors。
好了,到此为止,我们已经讲解了,如何优雅的实现防抖。注意:如果某个View不需要点击事件或防抖,还是用原来的findViewById,不要调这个findClickView,因为findClickView会增加点击事件的监听。