Sollte ich LifecycleOwner in ViewModel einschließen?

Lesezeit: 4 Minuten

Benutzeravatar von Hiroga Katageri
Hiroga Katageri

LifecycleOwner wird derzeit benötigt, damit ich einen Beobachter erstellen kann.

Ich habe Code, der einen Beobachter im ViewModel erstellt, also hänge ich den LifecycleOwner an, wenn ich das ViewModel in meinem Fragment abrufe.

Laut Googles Dokumentation.

Achtung: Ein ViewModel darf niemals auf eine Ansicht, einen Lebenszyklus oder eine Klasse verweisen, die möglicherweise einen Verweis auf den Aktivitätskontext enthält.

Habe ich diese Warnung gebrochen, und wenn ja, wie empfehlen Sie mir, meine Erstellung eines Beobachters für die Datenrückgabe zu verschieben?

Ich habe nur einen Beobachter gemacht, also frage ich mich, ob es noch gültig ist. Da auch in Googles Dokumentation stand es auch.

ViewModel-Objekte können LifecycleObservers enthalten, z. B. LiveData-Objekte.

HauptFragment

private lateinit var model: MainViewModel

/**
 * Observer for our ViewModel IpAddress LiveData value.
 * @see Observer.onChanged
 * */
private val ipObserver = Observer<String> {
    textIp.text = it
    hideProgressBar()
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    model = ViewModelProviders.of(this).get(MainViewModel::class.java)
    model.attach(this)
}

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? =
        inflater?.inflate(R.layout.fragment_main, container, false)

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    buttonRetrieveIp.setOnClickListener {
        showProgressBar()
        model.fetchMyIp().observe(this, ipObserver) //Here we attach our ipObserver
    }
}

override fun showProgressBar() {

    textIp.visibility = View.GONE
    progressBar.visibility = View.VISIBLE
}

override fun hideProgressBar() {

    progressBar.visibility = View.GONE
    textIp.visibility = View.VISIBLE
}

MainViewModel

private var ipAddress = MutableLiveData<String>()
private lateinit var owner: LifecycleOwner

fun attach(fragment: MainFragment) {
    owner = fragment
}

/**
 * For more information regarding Fuel Request using Fuel Routing and Live Data Response.
 * @see <a href="https://github.com/kittinunf/Fuel#routing-support">Fuel Routing Support</a>
 * @see <a href="https://github.com/kittinunf/Fuel#livedata-support">Fuel LiveData Support</a>
 * */
fun fetchMyIp(): LiveData<String> {

    Fuel.request(IpAddressApi.MyIp())
            .liveDataResponse()
            .observe(owner, Observer {

                if (it?.first?.statusCode == 200) {//If you want you can add a status code checker here.

                    it.second.success {

                        ipAddress.value = Ip.toIp(String(it))?.ip
                    }
                }
            })
    return ipAddress
}

Update 1: Verbessertes ViewModel dank @pskink-Vorschlag zur Verwendung von Transformationen.

private lateinit var ipAddress:LiveData<String>

/**
 * Improved ViewModel since January 23, 2018 credits to <a href="https://stackoverflow.com/users/2252830/pskink">pskink</a> <a href="
 *
 * For more information regarding Fuel Request using Fuel Routing and Live Data Response.
 * @see <a href="https://github.com/kittinunf/Fuel#routing-support">Fuel Routing Support</a>
 * @see <a href="https://github.com/kittinunf/Fuel#livedata-support">Fuel LiveData Support</a>
 * */
fun fetchMyIp(): LiveData<String> {

    ipAddress = Transformations.map(Fuel.request(IpAddressApi.MyIp()).liveDataResponse(), {

        var ip:String? = ""

            it.second.success {

                ip = Ip.toIp(String(it))?.ip
            }
        ip
    })

    return ipAddress
}

  • versucht MediatorLiveData oder Transformations#map / Transformations#switchMap?

    – Pskink

    23. Januar 2018 um 7:34 Uhr


  • Ich habe es noch nicht getan, also gebe ich statt einer LiveData-Zeichenfolge eine MediatorLiveData zurück und füge beide Quellen hinzu und füge einen einzelnen Beobachter in meinem Fragment hinzu, richtig?

    – Hiroga Katageri

    23. Januar 2018 um 7:48 Uhr

  • erster Versuch Transformations Klasse – es scheint, dass es der einfachste Weg ist – wenn nicht, wenn es darum geht MediatorLiveData Was meinst du mit “beide Quellen”? Es gibt eine Quelle, die sich ändert, nicht wahr?

    – Pskink

    23. Januar 2018 um 7:49 Uhr


  • sehen LiveDaten umwandeln

    – Pskink

    23. Januar 2018 um 9:30 Uhr

  • Ich habe es jetzt verstanden, ich konnte es mithilfe von Transformationen zum Laufen bringen.

    – Hiroga Katageri

    23. Januar 2018 um 9:40 Uhr

Benutzeravatar von Vitaliy A
Vitalij A

Nein. Wenn Sie Änderungen von einigen beobachten möchten LiveData in deinem ViewModel Sie können verwenden observeForever() was nicht erfordert LifecycleOwner.

Denken Sie daran, diesen Beobachter zu entfernen ViewModel‘s onCleared() Veranstaltung:

val observer = new Observer() {
  override public void onChanged(Integer integer) {
    //Do something with "integer"
  }
}

liveData.observeForever(observer);

override fun onCleared() {
    liveData.removeObserver(observer) 
    super.onCleared()
}

Sehr gute Referenz mit Beispielen für LiveData beachten.

  • Dies scheint eine hilfreiche Antwort zu sein. Leider ist der Link zum Beobachten von LiveData defekt.

    – Steve Gelman

    9. Juli um 23:17 Uhr

Annahmen:

  1. Fuel bezieht sich auf Ihre ViewModel
  2. Fuel.request(IpAddressApi.MyIp()) ist eine Methode in Ihrem ViewModel
  3. IpAddressApi.MyIp() hat keinen Bezug zu Ihnen LifecycleOwner,

Wenn alle wahr sind, dann verletzen Sie es nicht. Solange Sie nicht an a vorbeikommen LifecycleOwner Verweis auf die ViewModel du bist sicher!

LifecycleOwnerbezieht sich auf eine Aktivität oder ein Fragment, da es die verschiedenen Android-Lebenszyklen besitzt, z. B. onCreate, onPause, onDestroy usw

  • Ich habe meine Frage mit zusätzlichen Informationen aktualisiert. Fuel ist mein HttpClient, Fuel.request ist eine Methode in Fuel, die eine FuelRouting-Schnittstelle in eine Anfrage umwandelt, wo ich einen Beobachter für die Rückgabe von meiner GET-Methode erstelle.

    – Hiroga Katageri

    23. Januar 2018 um 7:40 Uhr


in Kotlin das kann so etwas sein:

val mObserver = Observer<List<QueueTabData>> { myString->
// do something with myString
}

1393630cookie-checkSollte ich LifecycleOwner in ViewModel einschließen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy