RecyclerViewのAdapterにClickListenerのいい感じの渡し方とKotlinのラムダ式がチョットわかったはなし
みなさん、Itemの中にボタンがあるRecyclerViewのAdapterを実装するとき、そのボタンの押されたときの処理はどのように書いてますか。
自分は今までこんな感じで書いてました。
class MyAdapter(private val listener: ClickButtonListener) { override fun onBindViewHolder(holder: FriendListViewHolder, position: Int) { holder.view.button.setOnClickListener { listener.onClick("data") } } } interface ClickButtonListener { fun onClick(data: String) }
class ListFragment : Fragment(), Adapter.ClickButtonListener { val adapter = MyAdapter(this) override fun onClick(data: String) { /** ~~~~~ **/ } }
おそらく、どこかの記事を参考に意味もわからずコピペしたものです。
これは以下ように書き換えることができます。
class MyAdapter(private val listener: ClickButtonListener) { override fun onBindViewHolder(holder: FriendListViewHolder, position: Int) { holder.view.button.setOnClickListener { listener.onClick("data") } } } interface ClickButtonListener { fun onClick(data: String) }
class ListFragment : Fragment() { val adapter = MyAdapter(object : ClickButtonListener { override onIconClick(data: String) { /** ~~~~~ **/ } }) }
Fragmentに interface ClickButtonListener
の実装を渡してましたが、Adapterのインスタンス化時に同時に object
としてinterfaceの実装を渡せるようになり、すっきり書くことができるようになりました。
さらにこれは、以下のように書き換えることができるようになります。
class MyAdapter(private val onClick: (data: String) -> Unit) { override fun onBindViewHolder(holder: FriendListViewHolder, position: Int) { holder.view.button.setOnClickListener { onClick.invoke("data") } } }
class ListFragment : Fragment() { val adapter = MyAdapter { data -> // itで省略可 /** ~~~~~ **/ } }
さらにすっきりしました。
MyAdapter
では (data: String) -> Unit
の関数型を受け取るようにして、 ListFragment
ではadapterのインスタンス化時にラムダ式を渡すようにしました。