最近、広告タブレットに kotlin + MVVM + LiveData を導入しました。レイアウトxmlでButtonに紐づけたアクションが連打で誤動作してしまうため、連打防止用のカスタムセッターを作った話をします。
@BindingAdapter("android:paddingLeft")
public static void setPaddingLeft(View view, int padding) {
view.setPadding(padding,
view.getPaddingTop(),
view.getPaddingRight(),
view.getPaddingBottom());
}
@BindingAdapterアノテーションを付与したメソッドを定義することでレイアウトxmlからメソッドを呼び出すことができるものです。既存の名前を付けることでオーバーライドされ、任意の名前を作ることで新しくメソッドを作成することができます。
kotlin拡張関数とRxBindingを使って拡張ClickListenerを作ります。RxBindingはViewイベントをRxJavaで扱えるようにするライブラリです。 RxのThrottleFirstを使い、一度処理を受け付けたら一定時間は処理を無視するようにすることで連打を防止します。
fun View.setOnProtectBarrageClickListener(listener: View.OnClickListener){
clicks().throttleFirst(2000L, TimeUnit.MILLISECONDS)
.subscribe { listener.onClick(this) }
}
拡張ClickListenerを作成したので、これをDataBindingカスタムセッターと紐付けることでButtonに設定されたメソッドが連打で実行されないようにします。※BindingAdapterはpublicなクラス関数でないといけないのですが、kotlinで何故か実現できなかったためjavaになっています。(今後の課題ですね)
@BindingAdapter("app:onClick")
public static void setClick(View view, View.OnClickListener listener){
ViewExtensionKt.setOnProtectBarrageClickListener(view, listener);
}
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:onClick="@{() -> viewmodel.Hoge(...)}"
/>
今回は app:onClick に紐づけたのでこれで連打されてもviewmodel.Hoge() メソッドが連続して実行されることはありません。
これでDataBindingで指定したButtonのアクションに対しても連打をできないようにできました。カスタムセッターを用意することで汎用的に使うことができ、大分コードがスッキリします。
Mobility Technologies では共に日本のモビリティを進化させていくエンジニアを募集しています。話を聞いてみたいという方は、是非 募集ページ からご相談ください!