Programėlių kūrimo pasaulis nuolat keičiasi, o kartu su juo ir architektūriniai šablonai, padedantys kurti tvarias, testuojamas ir lengvai prižiūrimas programas. Vienas iš naujesnių ir vis didesnio populiarumo sulaukiančių šablonų Android platformoje yra MVI (Model-View-Intent). Šis straipsnis skirtas išsamiai apžvelgti MVI architektūrą, jos privalumus, trūkumus ir palyginti ją su kitais populiariais Android architektūriniais šablonais.
Kas yra MVI?
MVI, arba Model-View-Intent, yra vienakryptis duomenų srauto architektūrinis šablonas, įkvėptas Cycle.js ir kitų reaktyvaus programavimo koncepcijų. Pagrindinis MVI principas – griežtas duomenų srauto vienakryptiškumas. Tai reiškia, kad duomenys teka tik viena kryptimi: nuo vartotojo veiksmų (Intents) iki modelio (Model), kuris atnaujina būseną (State), o ši perduodama vaizdui (View) atvaizduoti.
MVI architektūrą sudaro trys pagrindiniai komponentai:
- Intent (Ketinimai): Reprezentuoja vartotojo veiksmus arba įvykius, kurie sukelia būsenos pokyčius. Tai gali būti mygtuko paspaudimas, teksto įvedimas, duomenų gavimas iš tinklo ir pan. Intent’ai yra nekintami (immutable) objektai.
- Model (Modelis): Atsakingas už verslo logikos vykdymą ir būsenos valdymą. Modelis gauna Intent’us, apdoroja juos ir atnaujina programos būseną. Dažnai naudojamas „Reducer” principas, kai nauja būsena sukuriama remiantis ankstesne būsena ir gautu Intent’u.
- View (Vaizdas): Atsakingas už būsenos atvaizdavimą vartotojui. Vaizdas stebi būsenos pokyčius ir atitinkamai atsinaujina. View neturi jokios verslo logikos ir tik atspindi jam pateiktą būseną.
MVI veikimo principas

Duomenų srautas MVI architektūroje vyksta cikliškai ir vienakryptiškai:
- Vartotojas atlieka veiksmą (pvz., paspaudžia mygtuką).
- Sukūriamas Intent objektas, reprezentuojantis šį veiksmą.
- Intent’as siunčiamas į Modelį.
- Modelis gauna Intent’ą ir, remdamasis juo bei dabartine būsena, sukuria naują būseną (State).
- Nauja būsena perduodama View.
- View atvaizduoja naują būseną vartotojui.
- Ciklas kartojasi.
Svarbu pabrėžti, kad būsena (State) MVI architektūroje yra nekintama (immutable). Tai reiškia, kad kiekvieną kartą, kai reikia pakeisti būseną, sukuriama nauja būsenos kopija su atliktais pakeitimais, o sena būsena lieka nepakitusi. Tai užtikrina būsenos nuoseklumą ir palengvina derinimo (debugging) procesą.
MVI privalumai
MVI architektūra turi keletą svarbių privalumų:
- Vienakryptis duomenų srautas: Lengviau sekti duomenų pokyčius, nes jie vyksta tik viena kryptimi. Tai palengvina klaidų paiešką ir programos supratimą.
- Būsenos nekintamumas: Užtikrina būsenos nuoseklumą ir padeda išvengti netikėtų būsenos mutacijų.
- Testuojamumas: MVI komponentai yra lengvai testuojami, nes jie yra aiškiai atskirti ir turi apibrėžtas atsakomybes. Galima testuoti Intent’us, Reducer’ius ir View atskirai.
- Reaktyvus programavimas: MVI puikiai dera su reaktyvaus programavimo bibliotekomis, tokiomis kaip RxJava ar Kotlin Coroutines, leidžiančiomis efektyviai valdyti asinchroninius įvykius.
- Aiškus atsakomybių atskyrimas: Kiekvienas komponentas (Intent, Model, View) turi aiškiai apibrėžtą atsakomybę, todėl kodas tampa lengviau skaitomas ir prižiūrimas.
- Lengvesnis būsenos valdymas: Viena, nekintama būsena, leidžia lengviau valdyti visus programos aspektus.
MVI trūkumai
Nepaisant daugybės privalumų, MVI architektūra turi ir keletą trūkumų:
- Didesnis kodo kiekis: Palyginti su paprastesniais šablonais, tokiais kaip MVP (Model-View-Presenter), MVI gali reikalauti daugiau kodo, ypač pradiniame etape.
- Aukštesnis mokymosi slenkstis: MVI koncepcija gali būti sudėtingesnė pradedantiesiems programuotojams, ypač tiems, kurie nėra susipažinę su reaktyviu programavimu.
- Potencialus našumo sumažėjimas: Dėl dažno naujų būsenos objektų kūrimo gali atsirasti našumo problemų, ypač sudėtingose programose su daug būsenos pokyčių. Tačiau šis trūkumas dažniausiai yra minimalus ir gali būti optimizuojamas.
- Gali būti sunkiau įdiegti smulkiuose, paprastuose projektuose, nes architektūros sudėtingumas gali viršyti naudą.
MVI palyginimas su kitais architektūriniais šablonais
Android programėlių kūrime dažnai naudojami ir kiti architektūriniai šablonai, tokie kaip MVP (Model-View-Presenter) ir MVVM (Model-View-ViewModel). Palyginkime MVI su šiais šablonais:
- MVI vs. MVP: MVP duomenų srautas yra dvikryptis (View bendrauja su Presenter, o Presenter su Model ir atvirkščiai). MVI duomenų srautas yra vienakryptis. MVI būsena yra nekintama, o MVP būsena gali būti keičiama. MVI dažnai naudojamas su reaktyviu programavimu, o MVP gali būti naudojamas ir be jo.
- MVI vs. MVVM: MVVM taip pat naudoja vienakryptį duomenų srautą (iš View į ViewModel ir atgal per duomenų susiejimą – data binding). Tačiau MVVM ViewModel’is tiesiogiai nekeičia būsenos, o pateikia stebimus duomenis (observable data), kuriuos View gali prenumeruoti. MVI naudoja nekintamą būseną, o MVVM būsena gali būti keičiama per stebimus duomenis. MVVM dažniausiai naudojamas su „Data Binding” biblioteka, o MVI gali būti naudojamas ir be jos.
Pasirinkimas tarp MVI, MVP ir MVVM priklauso nuo konkretaus projekto poreikių ir programuotojų patirties. MVI yra geras pasirinkimas sudėtingoms programoms su daug būsenos pokyčių, kurioms reikalingas griežtas duomenų srauto valdymas ir testuojamumas. MVP ir MVVM gali būti tinkamesni paprastesniems projektams.
Praktinis MVI įgyvendinimas
Nors MVI koncepcija yra universali, jos įgyvendinimas gali skirtis priklausomai nuo naudojamų bibliotekų ir programavimo kalbos. Android platformoje MVI dažnai įgyvendinamas naudojant Kotlin Coroutines arba RxJava reaktyvaus programavimo bibliotekas. Šios bibliotekos suteikia įrankius efektyviam asinchroninių įvykių valdymui ir duomenų srautų stebėjimui.
Dažnai MVI architektūroje verslo logika yra iškeliama į atskirus „Interactor” ar „UseCase” klases. Šios klasės atsakingos už konkrečių veiksmų atlikimą (pvz., duomenų gavimas iš tinklo, duomenų bazės operacijos) ir grąžina rezultatą Modeliui. Tai padeda išlaikyti Modelį švarų ir lengvai testuojamą.
Išvados
MVI yra modernus ir efektyvus architektūrinis šablonas, tinkantis sudėtingų Android programėlių kūrimui. Jis užtikrina vienakryptį duomenų srautą, būsenos nekintamumą ir lengvą testuojamumą. Nors MVI gali reikalauti daugiau pradinių pastangų ir turi aukštesnį mokymosi slenkstį, jis gali žymiai pagerinti programos kokybę, tvarumą ir prižiūrimumą ilgalaikėje perspektyvoje. Ypač rekomenduojama naudoti didesnės apimties projektuose, kuriems reikalinga stabili ir gerai testuojama architektūra.