Jak komunikovat mezi fragmenty a aktivitou pomocí ViewModel

Komunikace je pro vývojáře jedním z nejdůležitějších témat a lze jej realizovat mnoha způsoby. Úkolem však je udělat to nejjednodušším a optimalizovaným způsobem. Můžeme to provést pomocí statického souboru, ale dojde k problému s pamětí. Aby se zabránilo problému s pamětí, mnoho vývojářů dělá něco jako

(aktivita jako MainActivity) .passDataToAnotherFragment ()

Jaký je problém s tímto způsobem? Spojuje fragment se specifickou aktivitou a snižuje opakovatelnost. Jaký je doporučený způsob?

Google doporučuje použít doc (před ViewModel) doc. Proto musíme implementovat rozhraní do třídy aktivity. Podřízené fragmenty budou obsahovat odkaz na rozhraní implementované aktivitou. Data budou předávána metodami rozhraní.

pracovní tok komunikace pomocí rozhraní

Předpokládejme jednoduchý scénář, ve kterém máme dva fragmenty pod stejnou aktivitou, jeden pro zadání čísla a druhý pro zobrazení dvojitého (2 x vstup). Aktivita také zobrazí zprávu Váš vstup je 123.

Dokážete si představit, kolik kódu musíme napsat a kolik scénářů musíme zvládnout. Nebudu to podrobně popisovat, protože tento článek je spíše o nejjednodušším řešení než o demonstraci implementace rozhraní. Implementaci najdete zde.

Lehká cesta

Přichází ViewModel, aby nás zachránil před zpracováním velkého množství scénářů a implementačního rozhraní. Potřebujeme pouze vytvořit třídu ViewModel a vytvořit instanci ve fragmentu, ale pomocí rozsahu aktivity tak, aby byla dostupná pro všechny fragmenty aktivity včetně samotné aktivity.

pracovní tok komunikace pomocí ViewModel

Vytvořte třídu ViewModel

třída SharedViewModel: ViewModel () {
    val inputNumber = MeableLiveData  ()
}

Chcete-li emitovat nebo předávat data z našeho vstupního fragmentu, vytvořte ViewModel v rozsahu činnosti. K tomu musíme předat odkaz na aktivitu jako argument metody ViewModelProvides.of (). Noe pouze předá data objektu ViewModel, jako je tento

aktivita? .let {
    sharedViewModel = ViewModelProviders.of (it) .get (SharedViewModel :: class.java)
}

et_input.addTextChangedListener (objekt: TextWatcher {
    přepsat zábavu afterTextChanged (p0: Editovatelné?) {}

    přepsat zábavu beforeTextChanged (p0: CharSequence ?, p1: Int, p2: Int, p3: Int) {}

    přepsat zábavu onTextChanged (txt: CharSequence ?, p1: Int, p2: Int, p3: Int) {
        txt? .let {
            var vstup = 0
            if (txt.toString (). isNotEmpty ()) {
                input = txt.toString (). toInt ()
            }

            sharedViewModel? .inputNumber? .postValue (vstup)
        }
    }

V aktivitě stačí vytvořit instanci našeho ViewModelu a sledovat takto požadovaná data

val sharedViewModel = ViewModelProviders.of (this) .get (SharedViewModel :: class.java)

sharedViewModel.inputNumber.observe (this, Observer {
    je to? .let {
        // udělej něco s číslem
    }
})

A co výstupní fragment? Můžeme udělat totéž, aby výstupní fragment pozoroval data. Ale mějte na paměti, že musíme vytvořit instanci ViewModel v rámci aktivity, jinak Android vytvoří spíše samostatnou instanci než sdílení stejné instance a data nezískáme.

U výstupního fragmentu to takto

aktivita? .let {
    val sharedViewModel = ViewModelProviders.of (it) .get (SharedViewModel :: class.java)

    sharedViewModel.inputNumber.observe (this, Observer {
    je to? .let {
            // udělej něco s číslem
        }
    })
}

A je to. Zdrojový kód najdete zde.

StackOverflow diskuse

Happy Coding