質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

2回答

3235閲覧

RecyclerViemwのセルがタップされた時の処理の動きがわからない

kbayashi

総合スコア18

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2020/03/08 08:59

編集2020/03/08 10:35

今現在、「はじめてのAndroidプログラミング」という参考書でコードを打ちながら勉強しているのですが、処理の動きが理解できないところがあります。
分からないところは、RecyclerViewのセルがタップされた時に呼び出される関数がまずMainActivityのadapter.setOnItemCickListenerなのか、adapterのholder.setOnClickListenerなのかが分からないです。

関数の意味自体はこれであってますか?
adapterで関数型の変数listenerを宣言
setOnItemClickListernerで引数で受け取ったらlistenerに格納する
holder.itemView.setOnClickListenerでlistenerに格納されている関数にタップされたデータのidを渡して動かす。
MainActyvityのadapter.setOnItemClickListenerで、listenerにScheduleEditActivityに選択されたidを渡して画面遷移する。

adapter

1package com.example.myscheduler 2 3import android.text.format.DateFormat 4import android.view.LayoutInflater 5import android.view.View 6import android.view.ViewGroup 7import android.widget.TextView 8import androidx.recyclerview.widget.RecyclerView 9import io.realm.OrderedRealmCollection 10import io.realm.RealmRecyclerViewAdapter 11 12class ScheduleAdapter(data: OrderedRealmCollection<Schedule>): 13//第一引数:表示したい項目,第2引数セルに表示するビューを保持 14//コンストラクタ 15// 第一:RecyclerViewに表示するデータ 16//第2:trueの場合表示を自動更新 17 RealmRecyclerViewAdapter<Schedule, ScheduleAdapter.ViewHolder>(data, true){ 18 19 private var listener: ((Long?)-> Unit)? = null 20 21 fun setOnItemClickListener(listener:(Long?)-> Unit){ 22 this.listener = listener 23 } 24 25 init{ 26 //RecyclerViewを高速描画するために必要 27 setHasStableIds(true) 28 } 29 //セルに使用するビューを保持したもの 30 //引数:セルに使用するビュー 31 class ViewHolder(cell: View) : RecyclerView.ViewHolder(cell){ 32 //xmlファイル内のテキストビューをセルに使う 33 val date: TextView = cell.findViewById(android.R.id.text1) 34 val title: TextView = cell.findViewById(android.R.id.text2) 35 } 36 //セルが必要となるたびに呼び出される 37 //引数第一:追加先のViewGroup 38 //第2:新しいビューのタイプ(使わない) 39 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ScheduleAdapter.ViewHolder { 40 //xmlファイルからビューを生成するためインスタンスを生成 41 val inflater = LayoutInflater.from(parent.context) 42 //レイアウトxmlからビューを生成 43 val view = inflater.inflate(android.R.layout.simple_list_item_2, 44 parent, false) 45 46 return ViewHolder(view) 47 } 48 49 50 //ビューホルダーに保存されたビューにデータなどを設定する 51 override fun onBindViewHolder(holder: ScheduleAdapter.ViewHolder, position: Int) { 52 //データベースから項目取得 53 val schedule: Schedule? = getItem(position) 54 //値をセット 55 holder.date.text = DateFormat.format("yyyy/MM/dd", schedule?.date) 56 holder.title.text = schedule?.title 57 //セルがタップされた時 58 holder.itemView.setOnClickListener{ 59 listener?.invoke(schedule?.id) 60 } 61 } 62 63 //IDを返す。高速化に必要 64 override fun getItemId(position: Int): Long { 65 return getItem(position)?.id ?: 0 66 } 67} 68

MainActyvity

1class MainActivity : AppCompatActivity() { 2 //lateinit型: val初期化をOnCreateまで遅らせる 3 private lateinit var realm: Realm 4 5 override fun onCreate(savedInstanceState: Bundle?) { 6 super.onCreate(savedInstanceState) 7 setContentView(R.layout.activity_main) 8 setSupportActionBar(toolbar) 9 //インスタンスを取得 10 realm = Realm.getDefaultInstance() 11 //レイアウトマネージャの役割:セルの配置方法を決める 12 // セルを直列に並べる 13 list.layoutManager = LinearLayoutManager(this) 14 //すべてのレコードを取得 15 val schedule = realm.where<Schedule>().findAll() 16 //表示したいレコードを渡してインスタンス化 17 val adapter = ScheduleAdapter(schedule) 18 //アダプターを設定 19 list.adapter = adapter 20 21 fab.setOnClickListener { view -> 22 val intent = Intent(this, ScheduleEditActivity::class.java) 23 startActivity(intent) 24 } 25 26 adapter.setOnItemClickListener { id-> 27 val intent = Intent(this, ScheduleEditActivity::class.java) 28 .putExtra("schedule_id", id) 29 startActivity(intent) 30 } 31 32 33 } 34 35 //アクティビティを終了 36 override fun onDestroy() { 37 super.onDestroy() 38 //リソース開放 39 realm.close() 40 } 41 42}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

RecyclerViewのセルがタップされた時に呼び出される関数がまずMainActivityのadapter.setOnItemCickListenerなのか、adapterのholder.setOnClickListenerなのか

どちらのメソッドもタップされた時には呼び出されません.

holder.itemView.setOnClickListener は, itemView がタッブされた時に実行する処理を 登録 します.
これによりタップ時に

listener?.invoke(schedule?.id)

が実行されるようになります.

adapter.setOnItemClickListener は, ScheduleAdapter 内で listener?.invoke によって実行する処理を 登録 します.
これによりタップ時に (listener?.invoke(schedule?.id) を経由して)

id -> val intent = Intent(this, ScheduleEditActivity::class.java).putExtra("schedule_id", id) startActivity(intent)

が実行されるようになります.

投稿2020/03/08 19:57

jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

まず、ボタンの OnClickListener を確認しましょう。例えば MainActivity の onCreate に

Kotlin

1 val button = findViewById<Button>(R.id.button) 2 button.setOnClickListener { view -> 3 Toast.makeText(this, "Button is clicked", Toast.LENGTH_SHORT).show() 4 }

と書いてあったとして、{ view -> ... } の部分はラムダ式と言って、ボタンが押された時に実行する処理を記述したもので、その場では実行されません。onCreate の中ではこのラムダ式をボタンに登録するだけで、実際にラムダ指揮が実行されるのがボタンが押された時になります。
(setOnClickListener の括弧が省略されているのが紛らわしいかもしれません。括弧を省略せずに書くと button.setOnClickListener( { view -> ... } ) であり、ラムダ式を引数として setOnClickListener メソッドを呼び出しているのが分かると思います。)

RecyclerView の場合もどのタイミングで何が実行されるかを考えるのが重要ですが、考えるべきタイミングは 1) onCreate の中、2) セルを用意する時、3) セルが押された時、の 3 種類になります。

まず、onCreate の中ではラムダ式 { id -> ... } を引数として adapter の setOnItemClickListener メソッドを呼び出しています。

MainActivity

1 adapter.setOnItemClickListener { id-> 2 val intent = Intent(this, ScheduleEditActivity::class.java) 3 .putExtra("schedule_id", id) 4 startActivity(intent) 5 }

adapter では、渡されたラムダ式を listener という変数に保存しているだけです。

adapter

1class ScheduleAdapter(data: OrderedRealmCollection<Schedule>): 2 RealmRecyclerViewAdapter<Schedule, ScheduleAdapter.ViewHolder>(data, true){ 3 4 private var listener: ((Long?)-> Unit)? = null 5 6 fun setOnItemClickListener(listener:(Long?)-> Unit){ 7 this.listener = listener 8 }

次に、セルを用意する時は onBindViewHolder が呼ばれて、itemView が押された時にラムダ式 { listener?.invoke(schedule?.id) } が実行されるように登録されます。
ここで、listener というのは MainActivity の onCreate にあったラムダ式で、invoke はそれを実行する、その際に schedule?.id、つまりこのセルに表示している項目の id が引数となります。

adapter

1 override fun onBindViewHolder(holder: ScheduleAdapter.ViewHolder, position: Int) { 2 //データベースから項目取得 3 val schedule: Schedule? = getItem(position) 4 5 // 略 6 7 //セルがタップされた時 8 holder.itemView.setOnClickListener{ 9 listener?.invoke(schedule?.id) 10 } 11 }

最後に、セルが押された時は { listener?.invoke(schedule?.id) } が実行され、listener の実体、つまり

MainActivity

1 { id-> 2 val intent = Intent(this, ScheduleEditActivity::class.java) 3 .putExtra("schedule_id", id) 4 startActivity(intent) 5 }

が呼び出されて画面遷移する、という流れになります。

投稿2020/03/08 12:31

hoshi-takanori

総合スコア7901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kbayashi

2020/03/09 00:34

回答ありがとうございます。 ラムダ式って()が省略されているので非常にややこしいですね。onCreateでadapterのsetOnItemClickListeneを呼び出しているとは微塵も思いませんでした。 流れとしては MainActivityのOnCreateでsetOnItemClickListeneに引数を渡してよびだし、 listenerに引数で渡したラムダ式を保存。 onBindViewHolder でitemViewがタップされた時のラムダ式を登録。 そしてタップされた時に登録していたラムダ式を使って、 listenerに保存されていたラムダ式を呼び出すのですね。 丁寧に解説してくださり、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問