MoTLab -Mobility Technologies Engineering Blog-MoTLab -Mobility Technologies Engineering Blog-

Android DataBindingで連打防止カスタムセッターを作る

行灯LaboAndroid
December 14, 2018

💁🏻
※本記事は Mobility Technologies の前身である JapanTaxi 時代に公開していたもので、記事中での会社やサービスに関する記述は公開当時のものです。
An image from Notion

最近、広告タブレットに kotlin + MVVM + LiveData を導入しました。レイアウトxmlでButtonに紐づけたアクションが連打で誤動作してしまうため、連打防止用のカスタムセッターを作った話をします。

DataBindingカスタムセッターとは

@BindingAdapter("android:paddingLeft")
public static void setPaddingLeft(View view, int padding) {
   view.setPadding(padding,
                   view.getPaddingTop(),
                   view.getPaddingRight(),
                   view.getPaddingBottom());
}

@BindingAdapterアノテーションを付与したメソッドを定義することでレイアウトxmlからメソッドを呼び出すことができるものです。既存の名前を付けることでオーバーライドされ、任意の名前を作ることで新しくメソッドを作成することができます。

連打防止拡張ClickLinsterを作る

kotlin拡張関数とRxBindingで拡張ClickListenerを作る

kotlin拡張関数とRxBindingを使って拡張ClickListenerを作ります。RxBindingはViewイベントをRxJavaで扱えるようにするライブラリです。 RxのThrottleFirstを使い、一度処理を受け付けたら一定時間は処理を無視するようにすることで連打を防止します。

fun View.setOnProtectBarrageClickListener(listener: View.OnClickListener){
    clicks().throttleFirst(2000L, TimeUnit.MILLISECONDS)
            .subscribe { listener.onClick(this) }
}

DataBindingカスタムセッターと紐付ける

拡張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 の前身である JapanTaxi 時代に公開していたもので、記事中での会社やサービスに関する記述は公開当時のものです。

Mobility Technologies では共に日本のモビリティを進化させていくエンジニアを募集しています。話を聞いてみたいという方は、是非 募集ページ からご相談ください!