4

I'm using View Binding from Kotlin Android Extensions:

import kotlinx.android.synthetic.main.fragment_user_profile.*

I want to display a value from Cloud Firestore in a fragment:

FirebaseFirestore.getInstance()
    .collection("users")
    .document("1")
    .get()
    .addOnSuccessListener { doc ->
        my_text_view.text = doc["name"] as String
    }

It works if the fragment is still shown when data is received. But if user close the fragment (pressing back) before data is received, it crashes:

java.lang.IllegalStateException: my_text_view must not be null

How do I avoid this?


Of course I can use my_text_view?.text = ... but

  • Someday I can forget to put ?

  • It doesn't solve the problem that the listener stays alive after the fragment is destroyed

I think I want something like addOnSuccessListener(Activity, OnSuccessListener) but for Fragment instead Activity

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Pavel
  • 5,374
  • 4
  • 30
  • 55

1 Answers1

2

You can check in your callback if the fragment is still added to its host activity,

FirebaseFirestore.getInstance()
.collection("users")
.document("1")
.get()
.addOnSuccessListener { doc ->
    if (isAdded) {
        my_text_view.text = doc["name"] as String
    }
}

However, a better solution would be to move your business logic to a viewmodel.

Francesc
  • 25,014
  • 10
  • 66
  • 84
  • It seems to me that `if (isAdded)` is by fact same as `my_text_view` null-checking (see my question edit) – Pavel Nov 28 '18 at 00:23
  • If I move business logic to a viewmodel, should I unsubscribe the listener when fragment is closed? – Pavel Nov 28 '18 at 00:25
  • 1
    If you use a ViewModel then you can listen to the viewmodel's data using LiveData, which handles the fragment lifecycle automatically, so you do not have to worry about subscribe/unsubscribe, happens automatically. – Francesc Nov 28 '18 at 00:26