今後は「イベントリスナー」は書かずに「イベントハンドラー」を書け!?

「イベントリスナー」と「イベントハンドラー」て分かってるようで分かってないような。

特に, Kotlin では混乱します。

一般的に「リスナー」と「ハンドラー」は定義として

「リスナーは起動するイベントを監視するもの」

「ハンドラーはイベントの処理を担当するもの」

混乱の原因として、同じオブジェクトをイベントのために監視(Listen)して処理(Handle)することがよくあります。

無名クラスをリスナーとしてセットして、それのメソッドがハンドラーのパターン。


cancelImage.setOnClickListener(object : View.OnClickListener { // 1
    override fun onClick(v: View?) { // 2
        dismiss()
    }
})

// 1 -> リスナー
// 2 -> ハンドラー

また、以下のようにリスナーと名前をつけてクラスを作ることができます。


class OnCancelSnackListener(
    val snackbar: Snackbar
): View.OnClickListener {
    override fun onClick(v: View?) {
        snackbar.dismiss()
    }
}

使い方:


cancelImage.setOnClickListener(OnCancelSnackListener(this))

一般的に、リスナーは「***Listener」、ハンドラーは「On***」と命名されます。

問題なのはラムダ記述の場合です。


cancelImage.setOnClickListener { dismiss() }

どれが「リスナー」なのか「ハンドラー」なのか。

リスナーオブジェクトは、Kotlinでは隠れてしまいます。

これは、setOnClickHandler と書くべきではないのかと思えたります。

ExJSなどjavascriptライブラリでは以下のような記述があります。


handler: function() {
}

listeners: {
   'click': function() {
   }
}

これらのJavaや他の言語の接尾語「***Listener」を使う慣習は歴史的な理由なだけです。

Kotlin stdlib や JetBrains のコードからそのことを確認できます。

自信をもって以下のように書きましょう。


fun setOnLoadedListener(handler: () -> Unit) {
   // Code
}
fun addOnFlingListener(handler: () -> Unit) {
   // Code
}

これまでどおり以下のようにも書くことができます。


fun setOnLoadedListener(listener: () -> Unit) {
   // Code
}
fun addOnFlingListener(listener: () -> Unit) {
   // Code
}

プロジェクトごとにどちらかに統一するのが良いでしょう。とな。

イベントハンドラとラムダ

Programmer dictionary: Event listener vs event handler


Kotlin で 非同期処理 Coroutine #1 ~ launch(), async()

ネット上を調べてみてもよくわかりません。

難しい言葉や experimental な仕様の変更などあったりして。

少しづつ試してみながらマスターしていきましょう。

// build.gradle

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.2"

//gradle.properties

kotlin.coroutines=enable

kotlinx.coroutines/coroutines-guide-ui.md at master · Kotlin/kotlinx.coroutines

まず、これ。


for (i in 1..10) {
  Timber.d("$i")
  Thread.sleep(1000)
}

非同期にしたいですよね。
launch から始めます。


launch { // @
  for (i in 1..10) {
    Timber.d("$i")
    Thread.sleep(1000)
  }
}


launch {
  for (i in 1..10) {
    Timber.d("$i")
    delay(1000)  // @
  }
}

引数をつけて渡す。

UI :
UIスレッドで実行。

CommonPool :
バックグランドスレッドで実行。


launch(UI) {  // @
  for (i in 1..10) {
    Timber.d("$i")
    delay(1000)
  }
}


launch(CommonPool) {  // @
  for (i in 1..10) {
    Timber.d("$i")
    delay(1000)
  }
}


launch(UI + CommonPool) {  // @
  for (i in 1..10) {
    Timber.d("$i")
    delay(1000)
  }
}

launch() の戻りからキャンセルできます。


val job = launch(UI) {  // @
  for (i in 1..10) {
    Timber.d("$i")
    delay(1000)
  }
}

fab.setOnClickListener {
  job.cancel() // @
}

 

まとめ

UIスレッドに限定されたコルーチンは、UIスレッドをブロックすることなく、UI内の何かを自由に更新して中断することができます。

delay が待っている間UIスレッドはブロックされないのでUIはフリーズしません。ただ単にコルーチンを中断します。

Job.cancelは完全にスレッドセーフでノンブロッキングです。
実際に終了するのを待つことなく、コルーチンがそのジョブをキャンセルするように通知するだけです。 どこからでも呼び出すことができます。

基本的な非同期呼び出しは、launch() と async() の2つ。似ているが戻りが異なる。


USB3.0 が WiFi 2.4Ghz に干渉しすぎて無駄にケーブルやアダプタが増えて金は減る

MacにUSB3.0ケーブルを差すとはっきりWiFiの接続が切れまくる。

もしや、と思い調べてみると。

USB3.0 機器から発生する高周波ノイズも、2.4Ghz無線LAN機器に大きく干渉し、良くない影響(通信速度の低下や通信断)が発生するようです。

USB3.0機器から発生するノイズは、2.4Ghz無線LANに悪影響を与えるらしい。 - ぼくんちのTV 別館

え、中華なケーブルやアダプタって買ってみて気づくこと多くない?

ネットのレビューやランキングって当てにならなくねえ?...

Apple 公式にも。

USB 3 デバイスがコンピュータに接続されていると、Wi-Fi または Bluetooth デバイスが正常に動作しないことがあります。なぜですか?

一部の USB 3 デバイスは、無線周波数干渉を引き起こすことがあります。これによって、2.4 GHz 帯を使用する Wi-Fi および Bluetooth デバイスとコンピュータとの通信に問題が生じる場合があります。

Mac で USB デバイスを使う - Apple サポート

この、WiFiの周波数の話は以前混線が気になっていたのが、もう4年前とか。

公衆無線LANとかWiFiが途切れる場合「5GHz帯」に切り替えたほうがいいんぢゃね?

今、同じアプリで計測してみると、2.4GHzはあいかわらず混雑で、5.0GHzも混んで来ている模様。

ルータを見てみると、今では旧型となり、2.4Ghz オンリー。

当然、飛んでいるWiFiのSSIDにも -g -gw のみ。


○○-a	IEEE802.11n	5GHz帯	        600Mbps
○○-aw	IEEE802.11a	5GHz帯	        54Mbps
○○-g	IEEE802.11n	2.4GHz帯	600Mbps
○○-gw	IEEE802.11g	2.4GHz帯	54Mbps

無線LANルーターのwifiのID内にある「g」「a」「gw」「aw」の意味 | JoyPlotライフ

買い替えますか、WiFiルータ。

【価格.com】無線LANルーター(Wi-Fiルーター) | 通販・価格比較・製品情報

最近のガジェットて使えるものなのに無駄に購入したりしてません?

もう2000円のルータを買おうと思います。 ← これが原因か! (笑)

👉 「これは分からないわ…」Mac miniで2.4GHz帯のWi-Fiが全く通信できないので調べてみたら1000円くらいで買った中華製のHDDケースに付いてたUSBケーブルが原因だった - Togetter 
👉 公衆無線LANとかWiFiが途切れる場合「5GHz帯」に切り替えたほうがいいんぢゃね?