From 51d65ed2cdcfa4964751e342b1f551c019fb4e4c Mon Sep 17 00:00:00 2001 From: SmartDengg Date: Wed, 5 Jun 2019 00:30:20 +0800 Subject: [PATCH] update readme commit sample code --- README.md | 56 ++++++++++++++----- .../plugin/DebounceExtension.groovy | 12 ++++ .../smartdengg/plugin/ForkJoinExecutor.groovy | 40 +++++++++++++ .../smartdengg/clickdebounce/ClickProxy.java | 33 +++++++++++ 4 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 click-debounce-gradle-plugin/src/main/groovy/com/smartdengg/plugin/DebounceExtension.groovy create mode 100644 click-debounce-gradle-plugin/src/main/groovy/com/smartdengg/plugin/ForkJoinExecutor.groovy create mode 100644 click-debounce-sample/src/main/java/com/smartdengg/clickdebounce/ClickProxy.java diff --git a/README.md b/README.md index cad984d..2fd462a 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,35 @@ [![](https://jitpack.io/v/SmartDengg/asm-clickdebounce.svg)](https://jitpack.io/#SmartDengg/asm-clickdebounce) -It is a gradle plugin that uses bytecode weaving technology to solve the click debounce problem of Android applications. +### Support incremental compilation! Support parallel compilation! Faster compilation speed, and shorter compilation time. -Safe, efficient, easy to use, support incremental build to avoid waste of build time. +It is a gradle plugin that uses bytecode weaving technology to solve the click jitter problem of Android applications. -I also wrote a **[blog](https://www.jianshu.com/p/28751130c038)** to share my ideas to solve the click debounce. +For example, a normal `onClick` method without any debounce plan, multiple quick clicks may trigger multiple Activity starts: + +```java + @Override public void onClick(View v) { + startActivity(new Intent(MainActivity.this, SecondActivity.class)); + } +``` + +modify the bytecode at compile time to: + +```java + @Debounced + public void onClick(View var1) { + if (DebouncedPredictor.shouldDoClick(var1)) { + startActivity(new Intent(this, SecondActivity.class)); + } + } +``` + + The `@Debounced` annotation indicates that the method has been debounced. The `shouldDoClick(View)` method will determine which are the jitters and which are the correct clicks. + +I also wrote a **[BLOG](https://www.jianshu.com/p/28751130c038)** to share my ideas to solve the click jitter. + +*Note: This repository is just a gradle plugin, responsible for bytecode weaving work. Android runtime library please move [here](https://github.com/SmartDengg/asm-clickdebounce-runtime).* -*Note: This repository is just a gradle plugin, responsible for bytecode weaving work, Android runtime library please move [here](https://github.com/SmartDengg/asm-clickdebounce-runtime).* ## Requirements @@ -50,7 +72,7 @@ buildscript { **Step 2**. Apply it in your module: -*It supports 'com.android.application', 'com.android.library' and 'com.android.feature'*. +Supports 'com.android.application', 'com.android.library' and 'com.android.feature'. ```groovy @@ -59,16 +81,24 @@ apply plugin: 'smartdengg.clickdebounce' ``` +**Step 3 (Optional)**. By adding the following code to your `build.gradle` to enable printe the beautiful log or add an exclusive list to indicate which methods do not need to be debounced. By default, the log is not printed, and process all the methods in the [support](#jump) list. -**Step 3 (Optional)**. Enable logging by adding the following code to your build.gradle: +**It is not recommended to manually add @Debounce annotations to methods, you should use the exclusive feature.** ```groovy -debounce.loggable = true +debounce { + // logable + loggable = true + // asm description [class: [methods]] + exclusion = ["com/smartdengg/clickdebounce/ClickProxy": ['onClick(Landroid/view/View;)V', + 'onItemClick(Landroid/widget/AdapterView;Landroid/view/View;IJ)V']] +} ``` -**Step 4 (Optional)**. Set the debounce window time(default is 300 milliseconds): + +**Step 4 (Optional)**. Set the debounce window time in your Java code(default is 300 milliseconds): ```java @@ -84,7 +114,7 @@ These file path is located in **buildDir/outputs/debounce/logs//**, as ``` . -+-- app(Apply this AGP) ++-- app (apply this AGP) | +-- build | +-- generated | +-- intermediates @@ -102,10 +132,8 @@ These file path is located in **buildDir/outputs/debounce/logs//**, as ``` -- **files.txt** :Record the class files consumed by this build,it can help you better understand the incremental build -- **classes.txt** :Record information about the classes and methods weaved in this build - - +- **files.txt** :Record the class files consumed by this build,it can help you better understand this build. +- **classes.txt** :Record information about the classes and methods weaved in this build. ## How it works @@ -114,7 +142,7 @@ These file path is located in **buildDir/outputs/debounce/logs//**, as ![](art/clickdebounce.png) -## Support +## Support - [x] [View.OnClickListener](https://developer.android.com/reference/android/view/View.OnClickListener) - [x] [AdapterView.OnItemClickListener](https://developer.android.com/reference/android/widget/AdapterView.OnItemClickListener) diff --git a/click-debounce-gradle-plugin/src/main/groovy/com/smartdengg/plugin/DebounceExtension.groovy b/click-debounce-gradle-plugin/src/main/groovy/com/smartdengg/plugin/DebounceExtension.groovy new file mode 100644 index 0000000..0617771 --- /dev/null +++ b/click-debounce-gradle-plugin/src/main/groovy/com/smartdengg/plugin/DebounceExtension.groovy @@ -0,0 +1,12 @@ +package com.smartdengg.plugin + +/** + * 创建时间: 2019/06/03 12:13
+ * 作者: SmartDengg
+ * 描述: + * */ +class DebounceExtension { + static final String NAME = "debounce" + boolean loggable + Map> exclusion = [:] +} diff --git a/click-debounce-gradle-plugin/src/main/groovy/com/smartdengg/plugin/ForkJoinExecutor.groovy b/click-debounce-gradle-plugin/src/main/groovy/com/smartdengg/plugin/ForkJoinExecutor.groovy new file mode 100644 index 0000000..4c0ea2d --- /dev/null +++ b/click-debounce-gradle-plugin/src/main/groovy/com/smartdengg/plugin/ForkJoinExecutor.groovy @@ -0,0 +1,40 @@ +package com.smartdengg.plugin + +import com.google.common.base.Preconditions +import com.google.common.collect.Sets + +import java.util.concurrent.ForkJoinPool +import java.util.concurrent.ForkJoinTask + +/** + * 创建时间: 2019/06/04 18:43
+ * 作者: SmartDengg
+ * 描述: */ +@Singleton +class ForkJoinExecutor { + + ForkJoinPool forkJoinPool = new ForkJoinPool() + private final Set> futureSet = Sets.newConcurrentHashSet() + + void execute(Closure task) { + ForkJoinTask submitted = forkJoinPool.submit(new Runnable() { + @Override + void run() { + task.call() + } + }) + boolean added = futureSet.add(submitted) + Preconditions.checkState(added, "Failed to add task") + } + + void waitingForAllTasks() { + try { + for (Iterator iterator = futureSet.iterator(); iterator.hasNext();) { + ForkJoinTask task = iterator.next() + task.join() + iterator.remove() + } + } finally { + } + } +} diff --git a/click-debounce-sample/src/main/java/com/smartdengg/clickdebounce/ClickProxy.java b/click-debounce-sample/src/main/java/com/smartdengg/clickdebounce/ClickProxy.java new file mode 100644 index 0000000..2e9ae3f --- /dev/null +++ b/click-debounce-sample/src/main/java/com/smartdengg/clickdebounce/ClickProxy.java @@ -0,0 +1,33 @@ +package com.smartdengg.clickdebounce; + +import android.util.Log; +import android.view.View; +import android.widget.AdapterView; + +/** + * 创建时间: 2019/06/03 11:58
+ * 作者: SmartDengg
+ * 描述: + */ +public class ClickProxy implements View.OnClickListener, AdapterView.OnItemClickListener { + + private static final String TAG = ClickProxy.class.getSimpleName(); + private static volatile ClickProxy instance; + + static ClickProxy getInstance() { + synchronized (ClickProxy.class) { + if (instance == null) { + instance = new ClickProxy(); + } + return instance; + } + } + + @Override public void onClick(View v) { + Log.d(TAG, "onClick : " + this.getClass().getName()); + } + + @Override public void onItemClick(AdapterView parent, View view, int position, long id) { + Log.d(TAG, "onClick : " + this.getClass().getName()); + } +}