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

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

新規登録して質問してみよう
ただいま回答率
85.46%
Kotlin

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

Q&A

解決済

1回答

727閲覧

ListenerRegistration、リスナーのデタッチができない

yukari00

総合スコア5

Kotlin

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

0グッド

0クリップ

投稿2020/06/20 05:39

編集2020/06/21 01:16

今、firebaseを使ってリアルタイムで情報を送受信して遊ぶちょっとしたゲームを作っています。

公式サイトには、リスナーのデタッチはlistener.remove()でできるとあったのですが、デタッチ出来てないみたいです。
listeningSelectedCards?.remove()
このすぐ下にログを入れたところ
Log -> D/listeningSelectedCards: com.google.firebase.firestore.core.ListenerRegistrationImpl@c3b3b7b

このように出ました。nullではないので、remove出来てないという認識でいいのでしょうか?それともこれはデタッチはできているのでしょうか?

<コード>
locateEachCardメソッドにListenerRegistrationを設置しました。
フラグメントを閉じた時に呼び出されるOnGoBackOnGameSettingFragmentメソッドでlistenerRegistrationをデタッチしました。(はずだが、されていなかった?)

Fragmentのコードもさらに下の方に載せました。

private fun locateEachCard() { listeningWords = database.collection(dbCollection).document(keyword).collection("words").document(keyword) .addSnapshotListener { it, e -> if (e != null) return@addSnapshotListener if (it == null || !it.exists()) return@addSnapshotListener val wordsDataList = mutableListOf<WordsData>() val hashmap = it["words"] as MutableList<HashMap<String, String>> for(i in 0 .. 24){ wordsDataList.add(WordsData(hashmap[i]["word"], hashmap[i]["color"])) } listeningSelectedCards = database.collection(dbCollection).document(keyword).collection("selectedCards").addSnapshotListener { query, e -> if(e != null) return@addSnapshotListener val selectedCardList = mutableListOf<WordsData>() supportFragmentManager.beginTransaction().remove(ResultFragment()).commit(); if(query == null || query.isEmpty){ remaining_red.setText("赤カードの残り枚数:") remaining_blue.setText("青カードの残り枚数:") red_number_of_remaining.setText("8") blue_number_of_remaining.setText("7") turn = Turn.RED_TEAM_TURN text_which_team_turn.setText("赤チームのターンです") } else{ willUpdate(query, selectedCardList) } newTurn() val listItem = mutableListOf<String>() val adapter = CardAdapter(wordsDataList, selectedCardList, object : CardAdapter.OnCardAdapterListener { override fun OnClickCard(word: String, wordsData: WordsData, holder: CardAdapter.ViewHolder) { showWhatYouClicked(listItem, word, wordsDataList) } }) recycler_view.layoutManager = GridLayoutManager(this, 5) recycler_view.adapter = adapter if(ifGameIsOver) showResultFragment() } } } . . . . . . . . override fun OnGoBackOnGameSettingFragment() { listeningWords?.remove() listeningSelectedCards?.remove() listeningMembers?.remove() Log.d("listeningSelectedCards", "$listeningSelectedCards" //D/listeningSelectedCards: com.google.firebase.firestore.core.ListenerRegistrationImpl@c3b3b7bと出ました teamToCollectAllCards = "" teamGotGray = null ifGameIsOver = false //下ではfirebaseの”selectedCards"というコレクションにあるドキュメントを一つ一つ処理しています。(もっと効率な方法あったら教えてください) database.collection(dbCollection).document(keyword).collection("selectedCards").get().addOnSuccessListener { for( i in 0 until it.documents.size){ val documentId = it.documents[i].id database.collection(dbCollection).document(keyword).collection("selectedCards").document(documentId).delete() } recycler_view.layoutManager = null recycler_view.adapter = null btn_explain.visibility = View.INVISIBLE text_which_team_turn.setText("") remaining_red.setText("") remaining_blue.setText("") blue_number_of_remaining.setText("") red_number_of_remaining.setText("") importWordsFromCSV() supportFragmentManager.beginTransaction() .replace(R.id.container_game, GameSettingFragment.newInstance(keyword, nickname)) .commit() } }

ゲーム終了時のResultフラグメントです。(ここからOnGoBackOnGameSettingFragmentメソッドを呼び出すので、載せておきます。)

class ResultFragment : Fragment() { . . . override fun onActivityCreated(savedInstanceState: Bundle?) { . . . btn_another_game_start.setOnClickListener { database.collection(dbCollection).document(keyword).update("readyForAnotherGame", true) } btn_back_game_setting.setOnClickListener { database.collection(dbCollection).document(keyword).update("readyToEndGame", true) } listening = database.collection(dbCollection).document(keyword).addSnapshotListener { it, e -> if (e != null) return@addSnapshotListener if (it == null ) return@addSnapshotListener val endGame = it.getBoolean("readyToEndGame")?: false Log.d("endGame", "$endGame") if(endGame){ listener?.OnGoBackOnGameSettingFragment() getFragmentManager()?.beginTransaction()?.remove(this)?.commit() return@addSnapshotListener } val tryAnotherGame = it.getBoolean("readyForAnotherGame")?: false Log.d("tryAnotherGame", "$tryAnotherGame") if(tryAnotherGame){ listener?.OnStartAnotherGame(turnCount) getFragmentManager()?.beginTransaction()?.remove(this)?.commit() return@addSnapshotListener } } } . .

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

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

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

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

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

kakajika

2020/06/20 13:19

該当箇所のコードを載せてください。
yukari00

2020/06/21 01:16

返信ありがとうございます。載せました????
guest

回答1

0

ベストアンサー

listeningSelectedCards?.remove()を呼んだらlisteningSelectedCardsにnullが代入されるということはありません。載せていただいたコードで問題なく購読の解除ができていると思います。

投稿2020/06/21 06:07

kakajika

総合スコア3131

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

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

yukari00

2020/06/21 08:29

返信ありがとうございます。しかし、デバッグログで確かめた結果(上のコードにはデバッグログまでは載せませんでしたが)resultFragment -> activityのOnGoBackOnGameSettingFragment() -> locateEachCard() との順に動いており、購読の解除が出来てないように見られます。OnGoBackOnGameSettingFragment()で解除したので、ここで止まって欲しいのですが、、それか何か別の要因でこのような事が起こってるのでしょうかね。。
kakajika

2020/06/21 08:51

すみません、購読解除のところだけコードを読んで回答してしまいました。。 listeningSelectedCardsを生成している箇所を見ると、listeningWordsのコールバック内でlisteningSelectedCardsを生成するようになっていますね。このコールバックは何度も呼ばれる可能性があるので、その度に新規の購読が登録されてしまって、前の購読が解除されていないのだと思います。 listeningSelectedCardsを生成する前にlisteningSelectedCards?.remove()を必ず呼ぶようにしてください。もしくは、LiveDataやRxJavaのswitchMapを利用するとシンプルに記述することもできます。
yukari00

2020/06/22 13:09

ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問