Je n'ai pas rencontré un bon article depuis longtemps ---- [Orienté aspect] Android gère les clics répétés sur les boutons avec élégance

Android gère les clics de bouton répétés avec élégance

 

 

Traitement précédent

Les méthodes trouvées en ligne ou auxquelles vous pourriez penser sont probablement les suivantes:

1. Dans chaque événement de clic de bouton, enregistrez le temps de clic et évaluez s'il dépasse l'intervalle de temps de clic.

private long mLastClickTime = 0;
public static final long TIME_INTERVAL = 1000L;
private Button btTest;
private void initView() {
    btTest = findViewById(R.id.bt_test);
    btTest.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            long nowTime = System.currentTimeMillis();
            if (nowTime - mLastClickTime > TIME_INTERVAL) {
                // do something
                mLastClickTime = nowTime;
            } else {
                Toast.makeText(MainActivity.this, "不要重复点击", Toast.LENGTH_SHORT).show();
            }
        }
    });
}

De cette façon, chaque événement de clic doit écrire un jugement temporel et beaucoup de code répété.

2. Encapsulez un événement de clic pour gérer le jugement de l'intervalle de clic

public abstract class CustomClickListener implements View.OnClickListener {
    private long mLastClickTime;
    private long timeInterval = 1000L;

    public CustomClickListener() {

    }

    public CustomClickListener(long interval) {
        this.timeInterval = interval;
    }

    @Override
    public void onClick(View v) {
        long nowTime = System.currentTimeMillis();
        if (nowTime - mLastClickTime > timeInterval) {
            // 单次点击事件
            onSingleClick();
            mLastClickTime = nowTime;
        } else {
            // 快速点击事件
            onFastClick();
        }
    }

    protected abstract void onSingleClick();
    protected abstract void onFastClick();
}

utilisation:

btTest.setOnClickListener(new CustomClickListener() {
    @Override
    protected void onSingleClick() {
        Log.d("xxx", "onSingleClick");
    }

    @Override
    protected void onFastClick() {
        Log.d("xxx", "onFastClick");
    }
});

Par rapport à la première méthode, cette méthode encapsule le jugement des clics répétés dans le CustomClickListener, et il n'est pas nécessaire de traiter le jugement de temps en externe, et seule la méthode de clic doit être implémentée.

3. Utilisez RxAndroid pour gérer les clics répétés

RxView.clicks(view)
    .throttleFirst(1, TimeUnit.SECONDS)
    .subscribe(new Consumer<Object>() {
        @Override
        public void accept(Object o) throws Exception {
            // do something
        }
     });

Gérez de manière réactive les clics sur les boutons et utilisez les opérateurs rxjava pour éviter les clics répétés. Par rapport aux première et deuxième solutions, cette méthode est plus élégante.

réfléchissez un moment:

Ces trois méthodes, quelle que soit celle-ci, sont très intrusives pour l'événement de clic d'origine. Soit vous devez ajouter une méthode à l'événement Click, soit vous devez remplacer tout l'événement Click. Alors, existe-t-il un moyen? Sans changer le logique originale, comment gérer correctement les clics répétés de boutons?

Une approche plus élégante

Ajoutez une logique de traitement unifiée à toutes les méthodes du même type, et nous pouvons rapidement penser à un mot: AOP , oui, programmation orientée aspect.

Comment utiliser AOP pour résoudre le problème des clics répétés?

1. Présentez Aspectj

Utilisez la programmation AOP sur Android, utilisez généralement la bibliothèque Aspectj

Debout sur les épaules de géants, Hujiang a ouvert le plugin Gradle d'Aspectj, ce qui nous permet d'utiliser Aspectj

  • Dans le build.gradle sous le répertoire racine du projet, ajoutez des dépendances:
dependencies {
     ......
     classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.0'
}
  • Dans le build.gradle sous l'application ou un autre répertoire de module, ajoutez:
// 注意:主App中请确保添加aspectjx
apply plugin: 'android-aspectjx'
dependencies {
    ......
    implementation 'org.aspectj:aspectjrt:1.8.9'
}

2. Ajoutez une annotation personnalisée

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SingleClick {
    /* 点击间隔时间 */
    long value() default 1000;
}

La raison de l'ajout d'annotations personnalisées est de faciliter la gestion des méthodes qui utilisent l'AOP des clics répétés, et en même temps, l'intervalle de temps de clic peut être passé dans les annotations, ce qui est plus flexible.

3. Encapsulez une classe d'outils de jugement de clic répété

public final class XClickUtil {

    /**
     * 最近一次点击的时间
     */
    private static long mLastClickTime;
    /**
     * 最近一次点击的控件ID
     */
    private static int mLastClickViewId;

    /**
     * 是否是快速点击
     *
     * @param v  点击的控件
     * @param intervalMillis  时间间期(毫秒)
     * @return  true:是,false:不是
     */
    public static boolean isFastDoubleClick(View v, long intervalMillis) {
        int viewId = v.getId();
        long time = System.currentTimeMillis();
        long timeInterval = Math.abs(time - mLastClickTime);
        if (timeInterval < intervalMillis && viewId == mLastClickViewId) {
            return true;
        } else {
            mLastClickTime = time;
            mLastClickViewId = viewId;
            return false;
        }
    }
}

4. Classe de traitement Ecrire Aspect AOP

@Aspect
public class SingleClickAspect {
    private static final long DEFAULT_TIME_INTERVAL = 5000;

    /** 
     * 定义切点,标记切点为所有被@SingleClick注解的方法
     * 注意:这里me.baron.test.annotation.SingleClick需要替换成
     * 你自己项目中SingleClick这个类的全路径哦
     */
    @Pointcut("execution(@me.baron.test.annotation.SingleClick * *(..))")
    public void methodAnnotated() {}

    /** 
     * 定义一个切面方法,包裹切点方法
     */
    @Around("methodAnnotated()")
    public void aroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        // 取出方法的参数
        View view = null;
        for (Object arg : joinPoint.getArgs()) {
            if (arg instanceof View) {
                view = (View) arg;
                break;
            }
        }
        if (view == null) {
            return;
        }
        // 取出方法的注解
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        if (!method.isAnnotationPresent(SingleClick.class)) {
            return;
        }
        SingleClick singleClick = method.getAnnotation(SingleClick.class);
        // 判断是否快速点击
        if (!XClickUtil.isFastDoubleClick(view, singleClick.value())) {
            // 不是快速点击,执行原方法
            joinPoint.proceed();
        }
    }
}

Instructions

private void initView() {
    btTest = findViewById(R.id.bt_test);
    btTest.setOnClickListener(new View.OnClickListener() {
        // 如果需要自定义点击时间间隔,自行传入毫秒值即可
        // @SingleClick(2000)
        @SingleClick
        @Override
        public void onClick(View v) {
            // do something
        }
    });
}

Une seule annotation est nécessaire pour éviter les clics répétés sur le bouton. Toutes les autres tâches sont transférées au compilateur. Le code est beaucoup actualisé.

 

 

 

--------------------------------------------

Présentation d'AspectJ

L'introduction d'Eclipse et d'Android Studio est différente. Cet article présente uniquement comment Android Studio présente AspectJ. Veuillez Baidu pour Eclipse. Android Studio doit être introduit dans le fichier build.gradle du module d'application, qui est divisé en 3 étapes:

1) Ajouter des dépendances principales

dependencies {
    ...
    compile 'org.aspectj:aspectjrt:1.8.9'
}

2) Ecrire le script de compilation gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.aspectj:aspectjtools:1.8.9'
        classpath 'org.aspectj:aspectjweaver:1.8.9'
    }
}

Je suppose que tu aimes

Origine blog.csdn.net/zwx_lucky/article/details/102543646
conseillé
Classement