Github项目解析(七)-->防止按钮重复点击

转载请标明出处:一片枫叶的专栏

本文中我将介绍一下我自己封装的一个小的工具类库:按钮点击事件类库。

作用:
该类库可以防止按钮重复点击,可以判断网络状态,可以判断用户登录状态,以及自定义验证条件等等。

说明:
其实现的核心原理就是通过自定义实现自身的OnClickListener类,并重写其中的onClick方法,在onClick方法中执行相应的判断逻辑之后回调我们自定义的抽象方法。

具体效果如下图所示:
《Github项目解析(七)-->防止按钮重复点击》” /></p><p><strong>使用方式</strong></p><ul><li>屏蔽多次点击事件</li></ul><pre><code><span>/** * 测试快速点击事件 */</span>
 fastButton.setOnClickListener(<span>new</span> OnClickFastListener() {
     <span>/** * 自定义实现的抽象方法,不在重写onClick方法,该方法用于执行点击后的逻辑 */</span> 
     <span>@Override</span>
     <span>public</span> <span>void</span> <span>onFastClick</span>(View v) {
         Toast.makeText(mContext, <span>, Toast.LENGTH_LONG).show(); } });

这里的fastButton就是一个普通的按钮组件,然后我们为该组件设置了点击事件,并且传入的是我们自定义的OnClickListener类(这里需要说明的是,不只是button组件任何View组件的点击事件都是可以的,这里只是以Button组件为例子),这里默认的屏蔽多次点击事件的时间间隔为900ms,也就是说当我们为组件设置了我们自定义的点击事件监听之后,假如有两次点击事件,并且第二次点击时若距离第一次点击事件小于0.9s,则第二次点击不会起作用;

  • 屏蔽网络情况
/** * 测试网络状况 */
networkButton.setOnClickListener(new OnClickNetworkListener() {
    /** * 自定义实现的抽象方法,主要用于执行有网络之后的逻辑 */
    @Override
    public void onNetworkClick(View v) {
        Toast.makeText(mContext, "当前设备有网络,执行后续操作...", Toast.LENGTH_LONG).show();
    }

    /** * 自定义实现的抽象方法,主要用于执行当前设备没有网络之后的逻辑 */
    @Override
    public void onNoNetworkClick(View v) {
        Toast.makeText(mContext, "当前设备没有网络...", Toast.LENGTH_LONG).show();
    }
});

同样的,这里的networkButton也是我们自定义的一个按钮组件,我们为其设置了点击事件监听,并传入了我们自定义的OnNetworkClickListener类,可以发现OnNetworkClickListener类中有两个回调方法,其中onNetworkClick方法用于执行当前设备有网的情况,而onNoNetworkClick方法用于处理当前设备没有网络的后续操作;

  • 屏蔽是否登录情况
/** * 测试是否登陆 */
loginButton.setOnClickListener(new OnClickLoginedListener(mContext) {

    /** * 自定义实现的抽象方法,用于判断当前设备是否登录 */
    @Override
    public boolean isLogined(Activity context, View view) {
        return false;
    }

    /** * 主要用于执行判断用户登录之后执行的逻辑 */
    @Override
    public void onLoginedClick(View v) {
        Toast.makeText(mContext, "设备已登录,之后后续操作...", Toast.LENGTH_LONG).show();
    }

    /** * 主要用于执行判断用户未登录之后执行的逻辑 */
    @Override
    public void onNoLoginedClick(View v) {
        Toast.makeText(mContext, "设备未登陆,无法执行后续操作...", Toast.LENGTH_LONG).show();
    }
});

这里的loginButton同样是我们自定义的一个按钮组件,并为其设置了我们的OnLoginedClickListener类,然后其中有三个回调方法,
其中方法isLogined用于判断当前用户是否登录,返回为true则表示用户已经登录,返回为false则表示用户未登录,具体实现逻辑需要在业务层实现,方法onLoginedClick用于执行登录之后的逻辑,而方法onNoLoginedClick用于执行用户尚未登录的逻辑。

这就是这个类库大概的实现功能,说完功能之后我们来看一下其具体实现逻辑:

实现方式

上面我们讲解了该类库的使用方式,那么我们是如何实现的呢?下面我们看一下该类库的源代码。

  • 防止按钮重复点击
/** * 方法按钮重复点击的监听类源码 */
public abstract class OnClickFastListener extends BaseClickListener {

    // 防止快速点击默认等待时长为900ms
    private long DELAY_TIME = 900;
    private static long lastClickTime;

    private boolean isFastDoubleClick() {
        long time = System.currentTimeMillis();
        long timeD = time - lastClickTime;
        if (0 < timeD && timeD < DELAY_TIME) {
            return true;
        }
        lastClickTime = time;
        return false;
    }

    @Override
    public void onClick(View v) {
        // 判断当前点击事件与前一次点击事件时间间隔是否小于阙值
        if (isFastDoubleClick()) {
            return;
        }

        onFastClick(v);
    }

    /** * 设置默认快速点击事件时间间隔 * @param delay_time * @return */
    public OnClickFastListener setLastClickTime(long delay_time) {

        this.DELAY_TIME = delay_time;

        return this;
    }

    /** * 快速点击事件回调方法 * @param v */
    public abstract void onFastClick(View v);
}

以上就是我们防止按钮重复点击的OnFastClickListener的源码了,可以看到这里我们定义了防止重复点击的OnClickListener对象,并重写了其onClick方法,可以看到我们在onClick方法中调用了isFastDoubleClick方法,该方法就是具体实现是否重复点击逻辑的,当按钮上一次点击的时间与本次点击的时间间隔小于900ms的时候isFastDoubleClick方法就会返回为true,这时候onClick方法直接返回,不在执行后续的onFastClick方法,否则就直接执行onFastClick方法。然后我们在为我们的View组件设置点击事件的时候只需要重写onFastClick方法就好了。。。

  • 按钮点击监听网络状况
/** * 判断当前设备是否有网络的监听类源码 */
public abstract class OnClickNetworkListener extends BaseClickListener {

    @Override
    public void onClick(View v) {
        boolean isNetworkOk = isNetworkConnected(v.getContext());

        if (isNetworkOk) {
            onNetworkClick(v);
        } else {
            onNoNetworkClick(v);
        }
    }

    // 点击事件--有网络
    public abstract void onNetworkClick(View v);

    // 点击事件--没有网络
    public abstract void onNoNetworkClick(View v);
    /** * 网络连接是否正常 * * @param context * @return */
    public static boolean isNetworkConnected(Context context) {
        if (context != null) {
            ConnectivityManager mConnectivityManager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
            if (mNetworkInfo != null) {
                return mNetworkInfo.isAvailable();
            }
        }
        return false;
    }
}

和刚刚的防止按钮重复点击事件类似,这里也是重写了自己的OnClickListener对象,然后重写了其onClick方法,并在其中执行isNetworkConnected方法,该方法就是判断是否当前设备是否有网络,若有网络则执行onNetworkClick方法,若无网络则执行onNoNetworkClick方法,这样当我们为自己的View组件设置点击事件的时候只需要为View组件设置onClickListener为我们自定义的OnClickListener对象,然后重写其中的onNetworkClick和onNoNetworkClick方法,其中onNetworkClick方法为有网络的回调方法,而onNoNetworkClick方法为无网络的回调方法。

  • 按钮点击监听是否登录
/** * 判断当前App用户是否登录的监听源码 */
public abstract class OnClickLoginedListener extends BaseClickListener {

    private Activity context = null;


    public OnClickLoginedListener(Activity context) {
        this.context = context;
    }

    @Override
    public void onClick(View view) {
        super.onClick(view);

        if (isLogined(context, view)) {
            onLoginedClick(view);
        } else {
            onNoLoginedClick(view);
        }
    }

    /** * 判断当前用户是否登录 * @param context * @param view * @return */
    public abstract boolean isLogined(Activity context, View view);

    /** * 用户登录之后执行的逻辑 * @param v */
    public abstract void onLoginedClick(View v);

    /** * 用户未登录执行点击事件 */
    public abstract void onNoLoginedClick(View v);
}

这里也是通过定义自身的OnClickListener类,然后重写其中的onClick方法,并在其中执行isLogined方法,该方法用于返回用户是否登录的逻辑判断,并且也是一个抽象的方法,所以也需要我们在业务层实现其具体的逻辑,然后我们重写了其中的onLoginedClick方法和onNoLoginedClick方法,其中onLoginedClick方法为用户登录之后的回调方法,而onNoLoginedClick方法为用户未登录之后执行的回调方法。

  • 定制化执行相应的业务逻辑
/** * 执行定制化判断逻辑的监听类源码 */
public abstract class OnClickCostomListener extends BaseClickListener {

    @Override
    public void onClick(View view) {
        super.onClick(view);

        if (isCorrect()) {
            onCorrentClick(view);
        } else {
            onNoCorrentClick(view);
        }
    }

    /** * 判断是否逻辑通过 * @return */
    public abstract boolean isCorrect();

    /** * 判断正确之后执行的逻辑请求 * @param v */
    public abstract void onCorrentClick(View v);

    /** * 判断失败之后执行的逻辑请求 * @param v */
    public abstract void onNoCorrentClick(View v);
}

可以看到这里重新定义了一个OnClickListener类,然后重写其中的onClick方法,首先执行判断方法isCorrect,然后若判断通过则执行onCorrentClick方法,若判断未通过则执行onNoCorrentClick方法。

这样我们就大概的分析了防止按钮重复点击类库的主要实现逻辑与功能,源码很简单,以后我会不断的开源与更新一些好用的类库的,希望大家多多支持。

总结:

  • 该类库主要是通过自定义OnClickListener类,并重写其中的onClick方法实现的;

  • 通过设置回调方法为抽象方法保证了我们必须要重写相应的回调方法;

  • 项目保存地址:Android-repeatclick,欢迎star和follow

另外对github项目,开源项目解析感兴趣的同学可以参考我的:
Github项目解析(一)–>上传Android项目至github
Github项目解析(二)–>将Android项目发布至JCenter代码库
Github项目解析(三)–>Android内存泄露监测之leakcanary
Github项目解析(四)–>动态更改TextView的字体大小
Github项目解析(五)–>Android日志框架
Github项目解析(六)–>自定义实现ButterKnife框架

    原文作者:一片枫叶_刘超
    原文地址: http://blog.csdn.net/qq_23547831/article/details/51730472
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞