Če se podajate v svet Androida, ste se zagotovo že srečali z večno dilemo, kako ravnati s podatki v predstavitveni plasti. Dolgo časa je vladal LiveData, toda s prihodom Kotlinovih korutin so se pojavila veliko močnejša in prilagodljivejša orodja. Govorimo o StateFlow in SharedFlow , ki sta v bistvu naravni razvoj reaktivnega in učinkovitega upravljanja podatkovnih tokov.
Resnica je, da čeprav se na prvi pogled zdita podobna koncepta, ima vsak svoj namen. Želeti, da si zaslon zapomni, kje se je novice končale, ni isto kot želeti poslati hitro obvestilo za opomnik, ki si ga je treba ogledati le enkrat. Da bi se izognili zmedi, si poglejmo, kako ti vroči tokovi delujejo in zakaj bi morali razmisliti o tem, da bi LiveData opustili v svojih sodobnih projektih.
Koncept pretoka: hladen ali vroč?
Da bi razumeli StateFlow in SharedFlow, morate najprej razumeti razliko med hladnim in vročim tokom. Standardni tok je hladen , kar pomeni, da je kot recept: nič se ne zgodi, dokler se nekdo ne odloči, da ga izvede (pokliče `collect`). Težava je v tem, da če imate tri naročnike, se koda proizvajalca izvede trikrat, kar lahko izprazni baterijo ali povzroči odvečne zahteve API-ja.
Tukaj pridejo na vrsto vroči tokovi. Tako StateFlow kot SharedFlow sta strateško vroči , kar pomeni, da proizvajalec ostane aktiven ne glede na to, ali kdo posluša. To omogoča več zbiralcem, da si delijo isti vir podatkov , kar preprečuje, da bi aplikacija vedno znova opravljala isto delo – kar je ključnega pomena za ohranjanje pretočnosti sistema.
StateFlow: Idealna zamenjava za LiveData
StateFlow je v bistvu vsebnik stanja. Njegova glavna značilnost je, da vedno vzdržuje trenutno vrednost , ki jo je mogoče sinhrono poizvedovati z uporabo lastnosti .value. Je odlično orodje za upravljanje stanja uporabniškega vmesnika, na primer ali se zaslon nalaga ali ali so bili podatki profila uspešno posodobljeni.
Za razliko od LiveData zahteva StateFlow začetno vrednost v svojem konstruktorju, kar odpravlja negotovost zaradi ničelnih stanj ob zagonu. Poleg tega izvaja obnašanje združevanja in deduplikacije : če dvakrat zaporedoma oddate isto vrednost, jo tok preprosto prezre. To je odlično za preprečevanje nepotrebnega osveževanja uporabniškega vmesnika, ko se podatki dejansko niso spremenili.
Za implementacijo tega v ViewModel je najboljši pristop uporaba zasebne rezervne lastnosti MutableStateFlow in njena izpostavitev kot nespremenljivega StateFlow. To zagotavlja, da lahko stanje spremeni samo ViewModel, pri čemer se spoštuje enosmerni pretok podatkov in prepreči, da bi pogled manipuliral s podatki.
SharedFlow: Vodilo dogodkov za edinstvena dejanja
Če je StateFlow za »stanje«, je SharedFlow za »dogodke«. Predstavljajte si, da želite prikazati pogovorno okno z napako ali se pomakniti na drug zaslon. Če uporabljate StateFlow, bi vrtenje naprave povzročilo, da bi novi zbiralnik prejel zadnjo vrednost in dogodek bi se znova sprožil – resna napaka. SharedFlow to rešuje, ker ga je mogoče konfigurirati z vrednostjo ponovitve nič.
Ta tok je veliko bolj prilagodljiv in nam omogoča prilagajanje parametrov, kot je prepolnitev medpomnilnika . Če se medpomnilnik napolni, se lahko odločimo, da pošiljatelja začasno ustavimo ali zavržemo najstarejšo ali najnovejšo vrednost. Ključna prednost je, da SharedFlow omogoča pošiljanje ponavljajočih se vrednosti ; če morate isto sporočilo »Napaka povezave« poslati trikrat, bo SharedFlow to storil brez oklevanja, medtem ko bi jih StateFlow filtriral.
Tehnična primerjava: StateFlow proti SharedFlow proti LiveData
Da bi se izognili zmedi na tehničnem razgovoru ali pri načrtovanju arhitekture, je pomembno upoštevati kritične točke. LiveData je preprost in samodejno upravlja življenjski cikel , vendar je zelo povezan z Androidom. StateFlow in SharedFlow, ki sta del Kotlin Coroutines, sta neodvisna od platforme , kar močno poenostavi testiranje enot in ustvarjanje čistih domenskih plasti.
- StateFlowVsili začetno vrednost, ima .value, odstrani podvojene vrednosti in je idealen za stanja uporabniškega vmesnika.
- SharedFlowNe zahteva začetne vrednosti, je konfiguriran glede ponovnega predvajanja in je prava možnost za kratkotrajne dogodke.
- LiveDataNe zahteva začetne vrednosti, zaveda se življenjskega cikla, vendar je manj zmogljiv pri asinhronih transformacijah.
Pomen varnega obiranja
Zelo pogosta napaka je izvajanje ukaza `collect` znotraj preprostega obsega korutine v dejavnosti. To je nevarno, ker bo tok nadaljeval z obdelavo podatkov, tudi ko je aplikacija v ozadju , kar lahko povzroči zrušitve ali prekomerno uporabo procesorja. Sodobna rešitev je uporaba API-ja `repeatOnLifecycle(Lifecycle.State.STARTED)`.
Ta funkcija povzroči, da se zbirka aktivira, ko je pogled viden, in se samodejno prekliče, ko doseže stanje STOPPED . Za Jetpack Compose je priporočena uporaba funkcije `collectAsStateWithLifecycle()` , ki to logiko izvorno integrira in zagotavlja, da aplikacija učinkovito uporablja vire naprave.
Pretvarjanje hladnih tokov v vroče
Včasih imamo tok, ki prihaja iz baze podatkov (kot je Room) ali repozitorija, in je hladen. Da ga segrejemo, uporabimo operatorja `stateIn` ali `shareIn` . Ta operatorja zahtevata `CoroutineScope` in strategijo zagona. Najpogostejši je `SharingStarted.WhileSubscribed(5000)`.
Ta konfiguracija je odlična, saj ohranja tok aktiven, dokler so naročniki, in če je zaslon zaprt, počaka 5 sekund, preden ustavi tok. To je ključnega pomena, da se med vrtenjem zaslona tok ne uniči in ponovno ustvari, s čimer se izognemo nepotrebnim zahtevam do strežnika ali lokalne baze podatkov.
Obvladovanje teh orodij vključuje razumevanje, da mora biti stanje trajno in deduplicirano z uporabo StateFlow, medtem ko morajo enkratna dejanja potekati prek SharedFlow. Z združevanjem tega z zavedanjem življenjskega cikla in transformacijo hladnega toka z uporabo stateIn dosežemo robustno, popolnoma reaktivno arhitekturo Android, optimizirano za delovanje v resničnem svetu na mobilnih napravah. Delite ta vodnik in pomagajte drugim, da se seznanijo s to temo.
