Cum să oprești utilizarea mvvm

Cum să oprești utilizarea mvvm

Dedicat tuturor celor care au fost atrasi de Biblioteca Databinding și care au decis să construiască aplicația pe MVVM, sunteți oameni curajoși!

Biblioteca de date

Început să se ocupe de Biblioteca Databinding.





Am avut impresia. Cei care sunt deja familiarizați cu aceasta vor înțelege, dar pentru restul lucrurilor, iată cum arată lucrarea cu această bibliotecă:

Cum să oprești utilizarea mvvm

Utilizarea Bibliotecii Databinding permite:

  • Scapa de apeluri pentru findViewById și setOnClickListener. Aceasta este specificarea id-ului în xml. puteți accesa vizualizarea prin link-ul .viewId. Și puteți seta apeluri de metode direct din xml;
  • Conectați datele direct la elementele de vizualizare. Se numește legare.setUser (utilizator). și în xml specificăm, de exemplu, android: text = "@";
  • Creați atribute personalizate. De exemplu, dacă dorim să încărcați imagini în ImageView folosind biblioteci Picasso, putem crea atribut BindingAdapter „URL a imaginii“, și scrie xml bind: url = „@“.
    Un astfel de BindingAdapter ar arăta astfel:






  • Efectuați starea de vedere dependentă de date. De exemplu, dacă se afișează indicatorul de descărcare, depinde de existența datelor.
  • Ultimul punct este deosebit de plăcut pentru mine deoarece statele au fost întotdeauna un subiect dificil. Dacă aveți nevoie să afișați trei stări pe ecran (descărcare, date, eroare), este în regulă. Dar, atunci când există cerințe diferite pentru starea elementelor în funcție de date (de exemplu, pentru a afișa textul numai dacă nu este gol sau își schimbă culoarea în funcție de valoarea), poate fi nevoie de un comutator de mare co toate variantele posibile ale stărilor de interfață, sau o mulțime de steaguri și codul în metodele de setare a valorilor la elemente.
    Prin urmare, faptul că Biblioteca Databinding facilitează lucrul cu statele este un plus imens. De exemplu, scrierea în xml android: visibility = "@". Nu ne mai putem gândi când să ascundem sau să afișăm TextView cu un nume de utilizator. Am setat numele și vizibilitatea se va schimba automat.

    Dar, începând să folosiți mai mult în mod activ baze de date, veți primi din ce în ce mai mult cod în xml. Și, pentru a nu transforma aspectul într-o groapă, vom crea o clasă în care vom extrage acest cod. Și în xml vor fi doar apeluri de proprietăți. Voi da un mic exemplu. Să presupunem că există o clasă utilizator:

    Și în UI vrem să vedem numele complet și să scriem în xml:

    Acest lucru nu este foarte de dorit pentru a vedea în xml. și creăm o clasă în care înducem această logică:

    Creatorii bibliotecii sugerează apelarea unor astfel de clase ViewModel (ca și în modelul MVVM, surprinzător).

    În exemplul respectiv, clasa este moștenită de la BaseObservable, iar în cod se numește notifyPropertyChanged (), dar aceasta nu este singura cale. De asemenea, puteți împacheta câmpurile din Observator, iar elementele UI dependente vor fi actualizate automat. Dar consider că această metodă este mai puțin flexibilă și rareori folosită.

    Acum, în xml vom avea:

    Mult mai bine, nu-i așa?

    Deci, avem o clasă ViewModel care acționează ca un strat între date și vizualizare. Ea se ocupă cu conversiile de date, controalele care câmpuri (și elementele UI asociate) și când sunt actualizate, conține logica modului în care un câmp depinde de ceilalți. Aceasta vă permite să ștergeți codul xml. În plus, este convenabil să folosiți această clasă pentru a gestiona evenimente din vizualizare (apăsare, etc.).

    Și atunci gândul vine la noi: dacă avem deja databinding. există o clasă ViewModel care conține logica afișajului, de ce să nu folosiți modelul MVVM?

    Acest gând vine în mod inevitabil. Pentru că ceea ce avem în prezent este foarte, foarte aproape de ceea ce este modelul MVVM. Să aruncăm o scurtă privire la ea.

    În modelul Model-View-ViewModel există trei componente principale:

    • Modelul. Logica de afaceri a aplicației care oferă datele de afișat.
    • View. Responsabil pentru aspectul, structura și structura tuturor elementelor UI pe care utilizatorul le vede pe ecran.
    • ViewModel. Acționează ca o punte între Vizualizare și Model și procesează logica afișajului. Solicită modelul pentru date și îl transmite Vizualizați într-o formă pe care View poate să o utilizeze cu ușurință. De asemenea, conține procesarea evenimentelor efectuate de utilizatorul aplicației în vizualizare, cum ar fi apăsarea unui buton. În plus, ViewModel este responsabil pentru definirea stărilor suplimentare de vizualizare care trebuie să fie afișate, de exemplu, dacă descărcarea este în desfășurare.

    Conectarea și interacțiunea dintre aceste componente pe care le vedem în imagine:

    Cum să oprești utilizarea mvvm

    Săgețile arată dependențele: View știe despre ViewModel, iar ViewModel știe despre Model, dar modelul nu știe nimic despre ViewModel, care nu știe nimic despre Vizualizare.

    Procesul este următorul: ViewModel solicită date din model și îl actualizează atunci când este necesar. Modelul notifică ViewModel că datele există. ViewModel prelucrează datele, le convertește și notifică vizualizarea că datele pentru interfața de utilizare sunt pregătite. Conexiunea dintre ViewModel și View se realizează prin legarea și afișarea automată a datelor. În cazul nostru, acest lucru se realizează prin utilizarea Bibliotecii Databinding. Cu databinding, vizualizarea este actualizată utilizând datele din ViewModel.

    Prezența cuplare automată (databinding) este principala diferență între acest model de modelul PresentationModel și MVP (MVP în Vizualizare prezentator schimbă apelând metode pe ea prin intermediul interfeței furnizate).

    MVVM pe Android

    Așa că am început să folosesc MVVM în proiectul meu. Dar, așa cum se întâmplă adesea în programare, teoria și practica nu sunt la fel. După finalizarea proiectului, am avut un sentiment de nemulțumire. Ceva a fost în neregulă cu această abordare, ceva ce nu mi-a plăcut, dar nu am putut înțelege ce a fost.

    Apoi am decis să desenez o schemă MVVM pe Android:

    Cum să oprești utilizarea mvvm

    Să luăm în considerare faptul că, ca urmare, se dovedește:

    ViewModel conține câmpurile utilizate în legături de date XML (Android: text = "@"), se ocupă de evenimentele cauzate în View (Android: onClick = "@"). Acesta solicită date din model, le convertește și, cu ajutorul memorării datelor, aceste date intră în vizualizare.

    Fragmentul execută simultan două roluri: un punct de intrare care asigură inițializarea și comunicarea cu sistemul și Vizualizare.

    Ce Fragment (sau activitate) sunt considerate în vedere înțelegerea modelelor și MVP MVVM, a devenit o practică comună, așa că nu voi insista asupra acestui.

    Pentru a supraviețui răsturnărilor și re-creare a Activității, vom lăsa ViewModel live pentru timpul în care vizualizarea este recreată (în acest caz Fragment). Acest lucru este realizat folosind pumnalul și domeniile personalizate. Nu voi intra în detalii, există deja o mulțime de articole bune despre pumnal. În cuvintele lor, se întâmplă următoarele:

    • ViewModel este creat cu ajutorul unui pumnal (și exemplul său trăiește în el), iar fragmentul îl ia când este necesar.
    • Atunci când un fragment moare în timp ce se rotește, îl sună pe DetachView () din ViewModel.
    • ViewModel continuă să trăiască, procesele de fundal prea, și este foarte convenabil.
    • Apoi, atunci când fragmentul este recreat, el numește attachView () și trece ca vizualizare (folosind interfața).
    • Dacă fragmentul moare complet, în loc de îndoire, omoară domeniul de aplicare (adus la zero componenta dorită pumnal. ViewModel și pot fi colectate gunoier „th împreună cu componenta) și ViewModel moare. Acest lucru este implementat în BaseFragment.

    De ce fragmentul se trece la ViewModel utilizând interfața MvvmView. Acest lucru este necesar pentru a putea apela comenzile "manual" pe Vizualizare. Nu totul se poate face cu ajutorul Bibliotecii Databinding.

    Dacă trebuie să salvați starea în cazul în care sistemul a ucis aplicația, putem salva și restabili starea ViewModel utilizând fragmentul savedInstanceState.

    Ceva de genul asta funcționează.

    Cititorul atenți va întreba: "Ce să suferiți de domenii personalizate pentru pumni. dacă puteți folosi doar Fragment ca un container și apelați setRetainInstance (adevărat) în el. " Da, puteți face asta. Dar, prin desenarea unei diagrame, am luat în considerare faptul că puteți utiliza Activity sau ViewGroup ca View.

    Recent am găsit un bun exemplu de implementare a MVVM. reflectând complet structura pe care am pictat-o. Cu excepția câtorva nuanțe, totul se face foarte bine. Uite, dacă e interesat.

    Problema dualității

    După ce am desenat diagrama și am gândit totul, mi-am dat seama că nu m-am bucurat de această abordare. Uită-te din nou la diagramă. Vedeți săgețile groase "databinding" și "comenzi manuale pentru vizualizare"? Aici este. Acum vă voi spune în detaliu.

    Odată ce avem databinding. majoritatea datelor pe care le putem seta pur și simplu în Vizualizare cu xml (prin crearea BindingAdapter, dacă este necesar). Dar există cazuri care nu se potrivesc acestei abordări. Acestea includ dialoguri, toasturi, animații, acțiuni întârziate și alte acțiuni complexe cu elemente de vizualizare.

    Să ne amintim un exemplu cu TextView:

    Ce se întâmplă dacă trebuie să setăm acest text folosind view.post (new Runnable ()). (Nu credem de ce, ne gândim cum)

    Puteți crea un BindingAdapter, în care să creați atributul "byPost" și să îl țineți cont de prezența atributelor listate ale elementului.

    Și de fiecare dată când TextView are ambele atribute specificate, acest BindingAdapter va fi folosit. Adăugați un atribut la xml:

    ViewModel ar trebui să aibă acum o proprietate care să indice că atunci când setăm valoarea, trebuie să folosim view.post (). Adăugați:

    Vedeți cât trebuie făcut totul pentru a realiza o acțiune foarte simplă?

    Prin urmare, este mult mai ușor să faceți astfel de lucruri direct pe Vedere. Adică folosiți interfața MvvmView, implementată de fragmentul nostru, și sunați la metodele de vizualizare (de asemenea, așa cum se face de obicei în MVP).

    Aici se manifestă problema dualității: lucrăm cu View în două moduri diferite. Una este automată (prin starea datelor), a doua este manuală (prin apeluri către comenzi din vizualizare). Personal nu-mi place.

    Problema statelor

    Se pare că avem într-un fel de a păstra nu numai starea View, ViewModel a prezentat un set de domenii, dar, de asemenea, practici care cauzează ViewModel la View.

    Această problemă poate fi rezolvată prin setarea în câmpurile de vizualizări ViewModel pentru fiecare caz separat. Acest lucru nu este foarte frumos și nu universal. Dar va funcționa.

    Despre state

    Problema statului mi-a dat ideea că starea obiectului poate fi reconstruit în două moduri: un set de parametri ce caracterizează starea sau un set de acțiuni care sunt necesare pentru aducerea elementului la starea dorită.

    Imaginați-vă un Cub al lui Rubik. Starea lui poate fi descrisă în 9 culori pe una dintre fețe. Și este posibil să folosiți un set de mișcări care îl vor conduce de la starea inițială la cea necesară.

    S-ar putea să aveți nevoie de o singură întoarcere și poate mai mult de nouă. Se pare că, în funcție de situație, un fel de descriere a stării este mai bun sau mai rău (mai puține date sunt necesare).

    În contextul raționamentului meu, o caracteristică a lui Moxy este interesantă - stochează starea de vizualizare ca un set de comenzi solicitate în această vizualizare. Și când am aflat prima dată despre asta, mi sa părut ciudat.

    Dar acum, după toate reflecțiile (pe care le-am împărtășit mai sus), cred că este o decizie foarte bună.
    Pentru că:

    • Nu este întotdeauna posibil (convenabil) să reprezinți o stare numai prin date (câmpuri).
    • În MVP, comunicarea cu vizualizarea se face prin apeluri către comenzi. De ce să nu o folosiți?
    • În realitate, numărul de câmpuri vizualizate. necesare pentru a-și recrea statutul, poate fi mult mai mult decât numărul de comenzi pe care le-a cauzat.

    În plus, această abordare oferă un plus. El, ca și Biblioteca de Informație, rezolvă problema unui număr mare de state diferite în felul său. De asemenea, nu trebuie să scrieți un comutator enorm. schimbarea interfeței utilizator în funcție de setul de câmpuri sau de numele uneia dintre stări, deoarece modificările sunt recreate printr-un set de apeluri metodice.

    Și totuși nu pot spune nimic despre Moxy. În opinia și opinia colegilor mei, pentru ziua de azi este cea mai bună bibliotecă care ajută la lucrul cu modelul MVP. Utilizează generarea de coduri pentru a minimiza efortul dezvoltatorului. Nu vă puteți gândi să implementați un model, ci să vă gândiți la funcționalitatea proiectului dvs. Și asta este bine.

    Dar destul despre MVP. Cu toate acestea, vorbim despre MVVM și este timpul să rezumăm.

    Îmi place MVVM ca un model, și nu-mi dispută protagoniștii. Dar, în majoritatea lor, ele sunt la fel ca alte modele sau sunt o chestiune de gust al dezvoltatorului. Da, și principalul avantaj este încă biblioteca. și nu modelul în sine.

    Conduita de simpatia pentru MVVM, mi-am dat seama de acest proiect. Pentru o lungă perioadă de timp a studiat subiectul, a analizat, a discutat și a oferit pentru el un set de dezavantaje ale acestui model:

    • MVVM vă obligă să lucrați simultan cu Vizualizați în două moduri: prin intermediul procesării datelor și prin metode de vizualizare.
    • Cu MVVM nu poate rezolva problema frumos condiții (necesitatea de a păstra metoda de apel View, cauzata in momentul in View a fost deconectat de la ViewModel).
    • Aveți nevoie de o utilizare avansată a Bibliotecii Databinding, care necesită timp pentru a stăpâni.
    • Codul în xml nu este totul plăcut.

    Da, vă puteți obișnui cu aceste dezavantaje. Dar, după gândit mult, am ajuns la concluzia că nu vreau să lucrez cu modelul care creează o fragmentare a abordărilor. Și am decis că voi scrie următorul proiect folosind MVP și Moxy.

    Folosești acest model - hotărăște-te singur. Dar te-am avertizat.

    PS: Biblioteca de date

    Finizați, poate, la fel, cu ceea ce au început - Biblioteca de date. Îmi place încă. Dar o să o folosesc doar într-o cantitate limitată:

    • Nu scrieți findViewById și setOnClickListener.
    • Și pentru a crea atributele xml convenabile folosind BindingAdapters (de exemplu, bind: font = "Roboto.ttf").

    Și asta e tot. Acest lucru va da un plus, dar nu se va lăuda cu MVVM.

    Dacă intenționați să lucrați și cu Biblioteca Databinding, iată câteva informații utile:

    Distribuiți acest lucru







    Trimiteți-le prietenilor: