SlideShare a Scribd company logo
1 of 18
Download to read offline
MVVMCROSS / MVVM 101
Na przykładach w Xamarin.Android
PRZEMYSŁAW RACIBORSKI
Wyjaśnijmy skrót - Model-View-ViewModel.
Intuicyjny, prawda?
Wzorzec MVVM polega na podzieleniu kodu aplikacji na trzy oddzielne warstwy:
DLACZEGO MVVM TO MVVM?
M/MODEL V/VIEW VM/VIEWMODEL
Klasy opisujące:
• nasz model danych
• dostęp do tych danych
• logikę biznesową, która
przetwarza dane
Widoki, inaczej nazywane
interfejsem użytkownika,
prezentujące już przetworzone dane
Warstwa pośrednia pomiędzy
Widokami (V) a Modelem (M).
MvvmCross zawiera wsparcie dla takich platform, jak:
• WPF
• UWP
• Xamarin.iOS
• Xamarin.Android
• Xamarin.Mac
• Xamarin.tvOS
• Aplikacje konsolowe
CZYM JEST MVVMCROSS?
Framework, który ułatwia zastosowanie wzorca MVVM w praktyce.
Główne funkcjonalności i założenia MvvmCross to:
• Dependency Injection (IoC) ad-hoc support
• Konfigurowalny system nawigacji pomiędzy widokami
• Wspomniany wcześniej system Bindingów View/ViewModel
• System pluginów – wsparcie dla funkcjonalności specyficznych dla platform jak chociażby obsługa
Lokalizacji, obsługa systemu plików, wykonywania połączeń telefonicznych czy wyboru zdjęć zrealizowana
za pomocą małych nugetowych paczek-pluginów
• Opakowanie oraz ułatwiony dostęp do natywnego API platform, np. MvvmCross Android Support Library
Zazwyczaj, aplikacja napisana przy użyciu MvvmCross składa się z jednego projektu PCL (Portable Class
Library – kod wspólny pomiędzy platformami) oraz n-projektów platform-specific.
• Zapoznanie się z dokumentacją i tutorialami przedstawionymi na MvvmCross.com
• Utworzenie projektu za pomocą MvvmCross Template (Xamarin Studio/Visual Studio add-in):
- ten wygeneruje nam podstawowy szkielet aplikacji wraz z podstawową konfiguracją projektu
Kod źródłowy aplikacji przedstawionej na prezentacji jest dostępny na githubie :
MVVMCROSS W PRAKTYCE
https://github.com/thefex/Xamarin-Cracow-Meetup.
Po stronie projektu PCL (Portable - kod współdzielony między platformami) potrzebujemy:
• LoginViewModel zawierający:
o Informację o nazwie użytkownika oraz wpisanym haśle (dane przekazane z widoku)
o Command, który powinien wywołać logikę logowania:
• czy wpisano poprawne dane - jeśli tak, przejdź na główny ekran, w przeciwnym wypadku wyświetl dialog
o Informację o tym czy wpisane dane są poprawne (czy możemy wywołać akcję logowania
• w tym przypadku czy przycisk „Sign in” jest klikalny)
• IAuthenticationService, tj. serwis realizujący proces logowania, zawierający:
o Logikę sprawdzającą czy dane logowania są poprawne
o Logikę zapisującą w trwałym kontenerze danych (nie ulegającym „zniszczeniu” po zamknięciu aplikacji) informację o tym, czy
użytkownik jest zalogowany. Skorzystamy z tego, aby przy następnym odpaleniu od razu przenieść użytkownika do głównego ekranu.
• IAuthenticationService zostaje wstrzyknięty do LoginViewModel. Nie tworzymy serwisów ręcznie.
MVVMCROSS W PRAKTYCE - EKRAN LOGOWANIA
Do implementacji ekranu logowania po stronie platformy (Android – widoki) musimy dodać LoginActivity.
Każda „strona” w Androidzie jest reprezentowana za pomocą Activity. Widoki w Androidzie są napisane przy pomocy plików .xml.
Przyjrzyjmy się kolejnym krokom:
1. Dodanie dwóch pól EditText – czyli Androidowych TextBoxów.
2. EditTextyy zawierające nazwę użytkownika i hasło powinny zostać podpięte pod pola LoginViewModel: Username i
Password. Zmiana wpisanego tekstu po stronie widoku powinna automatycznie zmieniać zawartość pól ViewModelu (i vice
versa).
3. Dodanie przycisku „Sign in” – kliknięcie na przycisk powinno wywoływać command LoginViewModel: SignIn. Brak wpisanej
nazwy użytkownika lub hasła powinien „zablokować” przycisk.
4. Do podpięcia kontrolek konieczne będzie skorzystanie ze składni MvvmCross „local:MvxBind
NazwaPropertyPoStronieKontrolki NazwaPropertyPoStronieViewModelu” – mechanizm bindingów.
MVVMCROSS W PRAKTYCE - EKRAN LOGOWANIA
W jaki sposób możemy zaimplementować wyświetlenie użytkownikowi dialogu w przypadku podania złych danych logowania?
Każda z platform zawiera różne API do wyświetlania dialogów – do żadnego z nich nie mamy dostępu w naszym „Core”
projektu – PCL (Portable Class Library).
Owszem, moglibyśmy w naszym ViewModelu wystawić pole w stylu „IsErrorDialogVisible”, a po stronie widoku moglibyśmy
reagować na zmianę tej właściwości poprzez wyświetlenie dialogu.
Jest to jednak rozwiązanie kiepskie – ogranicza nas do jednego stałego rodzaju dialogu, dodawanie i konfiguracja dialogów jest
na dłuższą metę problematyczna. Co więcej – nie możemy w łatwy sposób wykorzystać raz napisanego kodu wyświetlającego
dialog.
Rozwiązaniem jest skorzystanie z „Messengera” (w MvvmCross jest to plugin MvvmCross.Plugins.Messenger)
implementującego wzorzec EA – Event Aggregation.
MVVMCROSS W PRAKTYCE - EKRAN LOGOWANIA
Polega to na tym, że:
• po stronie PCL tworzymy klasy wiadomości zawierające dane opisującą wiadomość – np. DialogMessage zawierająca pola
jak Title czy Content,
• tworzymy Obserwatory obsługujące wiadomość – np. DroidDialogMessageObserver zawarty w projekcie Androida – w
reakcji na wiadomość o typie DialogMessage wyświetl Androidowy Dialog opisany przez DialogMessage,
• rejestrujemy obserwatory (np. po stronie Androidowych widoków) – rejestracja polega na tym, obserwatorzy zaczynają
nasłuchiwać/czekać na wiadomość,
• publikujemy wiadomość za pomocą Messengera (np. DialogMessage) – w chwili publikacji wszyscy aktualnie
zarejestrowani obserwatorzy obsłużą akcje powiązaną z wiadomością. Opublikować wiadomość jesteśmy w stanie w
projekcie Portable – nie zawiera to bowiem żadnego z API powiązanego z platformą.
W przykładowym projekcie dołączonym do prezentacji w ten sposób zaimplementowane jest wyświetlanie Toastów
(SnackBara), Dialogów oraz blokowanie interfejsu użytkownika przy operacji asynchronicznej.
Kolejnym z widoków przedstawionym w aplikacji jest widok prostej listy zawierającej dane jak:
• Imię
• Nazwisko
• Avatar
W Xamarinie najłatwiejszym sposobem na zaimplementowanie widoków z listami jest „podpięcie się” pod kolekcję
implementująca interfejs INotifyCollectionChanged (np. ObservableCollection<T>).
Przy zmianie pozycji/usunięciu/dodaniu elementu listy propagowany jest event zadeklarowany w interfejsie
INotifyCollectionChanged (CollectionChanged).
Przy każdej zmianie kolekcji event ten zawiera informację o tym w jaki sposób zmieniła się lista.
Niestety – poprawna implementacja list przy użyciu INotifyCollectionChanged jest problematyczna.
RX+DYNAMICDATA, A OBSERVABLECOLLECTION.
WPROWADZENIE DO LIST DANYCH
Wszystkie algorytmy (jak na przykład sortowanie) musielibyśmy napisać samodzielnie - tak aby w poprawny sposób został
propagowany event CollectionChanged.
Dodatkowo – wszystkie operacje na ObservableCollection są wywoływane na głównym wątku interfejsu – gdy spróbujemy to
zrobić na innym wątku aplikacja rzuci nam wyjątkiem.
Z pomocą przychodzi nam RX (Reactive Extensions) oraz biblioteka DynamicData, która jest w stanie wykonać za nas całą
pracę – tj. między innymi posortować, pogrupować dane na innych wątkach.
Temat RX/DynamicData moglibyśmy omawiać tygodniami – toteż jest to tylko krótkie wprowadzenie do tematu.
DynamicData jest biblioteką, która jest w stanie na podstawie: źródła danych i serii zadeklarowanych transformacji (w stylu
posortuj, pogrupuj, „przetransformuj” model) utworzyć ReadOnlyObservableCollection<>, która będzie „propagowała”
eventy CollectionChanged przy każdej z zadeklarowanych transformacji.
Dzięki prawidłowej propagacji eventu CollectionChanged nasze listy mogą reagować na każdą ze zmian animacją.
RX+DYNAMICDATA, A OBSERVABLECOLLECTION.
WPROWADZENIE DO LIST DANYCH
Aktualnie jedyną „słuszną” kontrolką do list w Androidzie jest RecyclerView. Listy wykonane przy użyciu RecyclerView
tworzą tylko n widocznych widoków, które są następnie „reużywane” (tzw. View recycling – stąd nazwa RecyclerView).
Dzięki takiemu rozwiązaniu aplikacje oparte na RecyclerView są wydajniejsze, zajmują mniej pamięci.
W świecie „Java-Android” czy Xamarina bez MvvmCross aby wyświetlić listę musimy zaimplementować
tzw. RecyclerAdapter – adapter, który wie skąd pobrać dane, ile ich jest, informujący RecylerView kiedy i gdzie
zmienił się jakiś element na liście.
MvvmCross załatwia to za programistę
wystarczy dodać paczkę MvvmCross.Support.V7.RecyclerView.
Na kolejnych slajdach zostaną przedstawione funkcjonalności RecyclerView opakowane przez MvvmCross.
Utworzenie prostej listy z 1 typem elementów wymaga dodania bindingów do źródła danych (ItemsSource)
oraz zdefiniowania atrybutu MvxItemTemplate, który powinien wskazywać na „layout” opisujący element listy.
NAJPROSTSZA LISTA PRZY UŻYCIU MVXRECYCLERVIEW
LISTA ZE WSPARCIEM RÓŻNYCH LAYOUTÓW - MVXITEMTEMPLATESELECTOR
Bazując na funkcjonalności znanej z Windows Phone/WPF, swego czasu do MvvmCross dorzuciłem funkcjonalność zwaną
„MvxItemTemplateSelector”. Dzięki temu dla jednej listy jesteśmy w stanie łatwo zdefiniować różne layouty dla jej elementów.
Aby skorzystać z tej funkcjonalności do atrybutu
„MvxTemplateSelector” należy wrzucić string, którego
wartość to: „Namespace.TemplateSelectorClassName,
AssemblyName”
Należy zaimplementować MvxTemplateSelector.
Zaimplementowane metody służą do wyboru layoutu
w zależności od danego elementy listy.
GRUPOWANIE A MVXRECYCLERVIEW
Niedawno do funkcjonalności MvxRecyclerView dodałem możliwość grupowania listy. Funkcjonalność jest jak do tej pory dostępna
jedynie w paczkach „unstable”. Aby dodać grupowanie do poprzedniej listy:
Należy dodać atrybut MvxGroupedDataConverter
analogicznie do MvxTemplateSelector. Należy określić
layout „headera” grupy za pomocą atrybutu
MvxGroupSectionLayoutId.
Należy zaimplementować interfejs
IMvxGroupedDataConverter, który na podstawie
elementu listy powinien utworzyć obiekt
MvxGroupedData.
HEADER/FOOTER - MVXRECYCLERVIEW
Kolejną z funkcjonalności list, którą dodałem do MvvmCross, jest obsługa Header/Footer list.
Aby dodać header/footer do poprzedniego przykładu:
Header/Footer definiujemy za
pomocą przekazania layoutu
do atrybutów:
• MvxHeaderLayoutId,
• MvxFooterLayoutId.
Dodatkowo możemy wykorzystać:
• MvxHidesHeaderIfEmpty,
• MvxHidesFooterIfEmpty.
To atrybuty, które ukrywają
header/footer, gdy lista jest pusta.
DZIĘKUJĘ ZA UWAGĘ!
PRZEMYSŁAW RACIBORSKI
In’saneLab Xamarin Developer

More Related Content

Similar to MvvmCross na przykładach w Xamarin.Android

Patronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 WarsztatyPatronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 Warsztatyintive
 
Jak stworzyć udany system informatyczny
Jak stworzyć udany system informatycznyJak stworzyć udany system informatyczny
Jak stworzyć udany system informatycznyqbeuek
 
Architektura aplikacji android
Architektura aplikacji androidArchitektura aplikacji android
Architektura aplikacji androidSages
 
Co nowego w ASP.NET MVC 4?
Co nowego w ASP.NET MVC 4?Co nowego w ASP.NET MVC 4?
Co nowego w ASP.NET MVC 4?tkryskiewicz
 
Poland- Smart Client Technology - MTS 2005
Poland- Smart Client Technology - MTS 2005Poland- Smart Client Technology - MTS 2005
Poland- Smart Client Technology - MTS 2005Tomasz Cieplak
 
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...Future Processing
 
Wzorce Repository, Unity of Work, Devexpress MVC w architekturze Asp.net MVC
Wzorce Repository, Unity of Work, Devexpress MVC  w architekturze Asp.net MVCWzorce Repository, Unity of Work, Devexpress MVC  w architekturze Asp.net MVC
Wzorce Repository, Unity of Work, Devexpress MVC w architekturze Asp.net MVCQuick-Solution
 
Nowe Trendy W Projektowaniu Aplikacji Webowych
Nowe Trendy W Projektowaniu Aplikacji WebowychNowe Trendy W Projektowaniu Aplikacji Webowych
Nowe Trendy W Projektowaniu Aplikacji WebowychMarcin Daczkowski
 
Xamarin.Forms - wprowadzenie
Xamarin.Forms - wprowadzenieXamarin.Forms - wprowadzenie
Xamarin.Forms - wprowadzenieTomasz Gibulski
 
Podstawy Asp.Net Mvc 1.0 W 3600 Sekund
Podstawy Asp.Net Mvc 1.0 W 3600 SekundPodstawy Asp.Net Mvc 1.0 W 3600 Sekund
Podstawy Asp.Net Mvc 1.0 W 3600 Sekundemdzej
 
Jak podwoić wartość kodu .NET?
Jak podwoić wartość kodu .NET?Jak podwoić wartość kodu .NET?
Jak podwoić wartość kodu .NET?javOnet
 
Michał Dec - Quality in Clouds
Michał Dec - Quality in CloudsMichał Dec - Quality in Clouds
Michał Dec - Quality in Cloudskraqa
 
Migracja I Integracja Bazy
Migracja I Integracja BazyMigracja I Integracja Bazy
Migracja I Integracja BazyPrzemysław ...
 
Cykl życia zapytania HTTP (pod maską)
Cykl życia zapytania HTTP (pod maską)Cykl życia zapytania HTTP (pod maską)
Cykl życia zapytania HTTP (pod maską)Laravel Poland MeetUp
 
Wprowadzenie do MEF w .NET 4.0
Wprowadzenie do MEF w .NET 4.0Wprowadzenie do MEF w .NET 4.0
Wprowadzenie do MEF w .NET 4.0Maciej Zbrzezny
 
Wprowadzenie do implementacji architektur plug-in w PHP
Wprowadzenie do implementacji architektur plug-in w PHPWprowadzenie do implementacji architektur plug-in w PHP
Wprowadzenie do implementacji architektur plug-in w PHPPHPCon Poland
 
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...The Software House
 

Similar to MvvmCross na przykładach w Xamarin.Android (20)

Silverlight i PHP
Silverlight i PHPSilverlight i PHP
Silverlight i PHP
 
Patronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 WarsztatyPatronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 Warsztaty
 
Jak stworzyć udany system informatyczny
Jak stworzyć udany system informatycznyJak stworzyć udany system informatyczny
Jak stworzyć udany system informatyczny
 
Architektura aplikacji android
Architektura aplikacji androidArchitektura aplikacji android
Architektura aplikacji android
 
Co nowego w ASP.NET MVC 4?
Co nowego w ASP.NET MVC 4?Co nowego w ASP.NET MVC 4?
Co nowego w ASP.NET MVC 4?
 
Poland- Smart Client Technology - MTS 2005
Poland- Smart Client Technology - MTS 2005Poland- Smart Client Technology - MTS 2005
Poland- Smart Client Technology - MTS 2005
 
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...
 
Wzorce Repository, Unity of Work, Devexpress MVC w architekturze Asp.net MVC
Wzorce Repository, Unity of Work, Devexpress MVC  w architekturze Asp.net MVCWzorce Repository, Unity of Work, Devexpress MVC  w architekturze Asp.net MVC
Wzorce Repository, Unity of Work, Devexpress MVC w architekturze Asp.net MVC
 
Nowe Trendy W Projektowaniu Aplikacji Webowych
Nowe Trendy W Projektowaniu Aplikacji WebowychNowe Trendy W Projektowaniu Aplikacji Webowych
Nowe Trendy W Projektowaniu Aplikacji Webowych
 
Xamarin.Forms - wprowadzenie
Xamarin.Forms - wprowadzenieXamarin.Forms - wprowadzenie
Xamarin.Forms - wprowadzenie
 
Podstawy Asp.Net Mvc 1.0 W 3600 Sekund
Podstawy Asp.Net Mvc 1.0 W 3600 SekundPodstawy Asp.Net Mvc 1.0 W 3600 Sekund
Podstawy Asp.Net Mvc 1.0 W 3600 Sekund
 
react-pl.pdf
react-pl.pdfreact-pl.pdf
react-pl.pdf
 
Jak podwoić wartość kodu .NET?
Jak podwoić wartość kodu .NET?Jak podwoić wartość kodu .NET?
Jak podwoić wartość kodu .NET?
 
Michał Dec - Quality in Clouds
Michał Dec - Quality in CloudsMichał Dec - Quality in Clouds
Michał Dec - Quality in Clouds
 
Migracja I Integracja Bazy
Migracja I Integracja BazyMigracja I Integracja Bazy
Migracja I Integracja Bazy
 
Cykl życia zapytania HTTP (pod maską)
Cykl życia zapytania HTTP (pod maską)Cykl życia zapytania HTTP (pod maską)
Cykl życia zapytania HTTP (pod maską)
 
Wprowadzenie do MEF w .NET 4.0
Wprowadzenie do MEF w .NET 4.0Wprowadzenie do MEF w .NET 4.0
Wprowadzenie do MEF w .NET 4.0
 
Wprowadzenie do implementacji architektur plug-in w PHP
Wprowadzenie do implementacji architektur plug-in w PHPWprowadzenie do implementacji architektur plug-in w PHP
Wprowadzenie do implementacji architektur plug-in w PHP
 
Pure MVC - Mediovski
Pure MVC - MediovskiPure MVC - Mediovski
Pure MVC - Mediovski
 
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
 

MvvmCross na przykładach w Xamarin.Android

  • 1.
  • 2. MVVMCROSS / MVVM 101 Na przykładach w Xamarin.Android PRZEMYSŁAW RACIBORSKI
  • 3. Wyjaśnijmy skrót - Model-View-ViewModel. Intuicyjny, prawda? Wzorzec MVVM polega na podzieleniu kodu aplikacji na trzy oddzielne warstwy: DLACZEGO MVVM TO MVVM? M/MODEL V/VIEW VM/VIEWMODEL Klasy opisujące: • nasz model danych • dostęp do tych danych • logikę biznesową, która przetwarza dane Widoki, inaczej nazywane interfejsem użytkownika, prezentujące już przetworzone dane Warstwa pośrednia pomiędzy Widokami (V) a Modelem (M).
  • 4. MvvmCross zawiera wsparcie dla takich platform, jak: • WPF • UWP • Xamarin.iOS • Xamarin.Android • Xamarin.Mac • Xamarin.tvOS • Aplikacje konsolowe CZYM JEST MVVMCROSS? Framework, który ułatwia zastosowanie wzorca MVVM w praktyce.
  • 5. Główne funkcjonalności i założenia MvvmCross to: • Dependency Injection (IoC) ad-hoc support • Konfigurowalny system nawigacji pomiędzy widokami • Wspomniany wcześniej system Bindingów View/ViewModel • System pluginów – wsparcie dla funkcjonalności specyficznych dla platform jak chociażby obsługa Lokalizacji, obsługa systemu plików, wykonywania połączeń telefonicznych czy wyboru zdjęć zrealizowana za pomocą małych nugetowych paczek-pluginów • Opakowanie oraz ułatwiony dostęp do natywnego API platform, np. MvvmCross Android Support Library Zazwyczaj, aplikacja napisana przy użyciu MvvmCross składa się z jednego projektu PCL (Portable Class Library – kod wspólny pomiędzy platformami) oraz n-projektów platform-specific.
  • 6. • Zapoznanie się z dokumentacją i tutorialami przedstawionymi na MvvmCross.com • Utworzenie projektu za pomocą MvvmCross Template (Xamarin Studio/Visual Studio add-in): - ten wygeneruje nam podstawowy szkielet aplikacji wraz z podstawową konfiguracją projektu Kod źródłowy aplikacji przedstawionej na prezentacji jest dostępny na githubie : MVVMCROSS W PRAKTYCE https://github.com/thefex/Xamarin-Cracow-Meetup.
  • 7. Po stronie projektu PCL (Portable - kod współdzielony między platformami) potrzebujemy: • LoginViewModel zawierający: o Informację o nazwie użytkownika oraz wpisanym haśle (dane przekazane z widoku) o Command, który powinien wywołać logikę logowania: • czy wpisano poprawne dane - jeśli tak, przejdź na główny ekran, w przeciwnym wypadku wyświetl dialog o Informację o tym czy wpisane dane są poprawne (czy możemy wywołać akcję logowania • w tym przypadku czy przycisk „Sign in” jest klikalny) • IAuthenticationService, tj. serwis realizujący proces logowania, zawierający: o Logikę sprawdzającą czy dane logowania są poprawne o Logikę zapisującą w trwałym kontenerze danych (nie ulegającym „zniszczeniu” po zamknięciu aplikacji) informację o tym, czy użytkownik jest zalogowany. Skorzystamy z tego, aby przy następnym odpaleniu od razu przenieść użytkownika do głównego ekranu. • IAuthenticationService zostaje wstrzyknięty do LoginViewModel. Nie tworzymy serwisów ręcznie. MVVMCROSS W PRAKTYCE - EKRAN LOGOWANIA
  • 8. Do implementacji ekranu logowania po stronie platformy (Android – widoki) musimy dodać LoginActivity. Każda „strona” w Androidzie jest reprezentowana za pomocą Activity. Widoki w Androidzie są napisane przy pomocy plików .xml. Przyjrzyjmy się kolejnym krokom: 1. Dodanie dwóch pól EditText – czyli Androidowych TextBoxów. 2. EditTextyy zawierające nazwę użytkownika i hasło powinny zostać podpięte pod pola LoginViewModel: Username i Password. Zmiana wpisanego tekstu po stronie widoku powinna automatycznie zmieniać zawartość pól ViewModelu (i vice versa). 3. Dodanie przycisku „Sign in” – kliknięcie na przycisk powinno wywoływać command LoginViewModel: SignIn. Brak wpisanej nazwy użytkownika lub hasła powinien „zablokować” przycisk. 4. Do podpięcia kontrolek konieczne będzie skorzystanie ze składni MvvmCross „local:MvxBind NazwaPropertyPoStronieKontrolki NazwaPropertyPoStronieViewModelu” – mechanizm bindingów. MVVMCROSS W PRAKTYCE - EKRAN LOGOWANIA
  • 9. W jaki sposób możemy zaimplementować wyświetlenie użytkownikowi dialogu w przypadku podania złych danych logowania? Każda z platform zawiera różne API do wyświetlania dialogów – do żadnego z nich nie mamy dostępu w naszym „Core” projektu – PCL (Portable Class Library). Owszem, moglibyśmy w naszym ViewModelu wystawić pole w stylu „IsErrorDialogVisible”, a po stronie widoku moglibyśmy reagować na zmianę tej właściwości poprzez wyświetlenie dialogu. Jest to jednak rozwiązanie kiepskie – ogranicza nas do jednego stałego rodzaju dialogu, dodawanie i konfiguracja dialogów jest na dłuższą metę problematyczna. Co więcej – nie możemy w łatwy sposób wykorzystać raz napisanego kodu wyświetlającego dialog. Rozwiązaniem jest skorzystanie z „Messengera” (w MvvmCross jest to plugin MvvmCross.Plugins.Messenger) implementującego wzorzec EA – Event Aggregation. MVVMCROSS W PRAKTYCE - EKRAN LOGOWANIA
  • 10. Polega to na tym, że: • po stronie PCL tworzymy klasy wiadomości zawierające dane opisującą wiadomość – np. DialogMessage zawierająca pola jak Title czy Content, • tworzymy Obserwatory obsługujące wiadomość – np. DroidDialogMessageObserver zawarty w projekcie Androida – w reakcji na wiadomość o typie DialogMessage wyświetl Androidowy Dialog opisany przez DialogMessage, • rejestrujemy obserwatory (np. po stronie Androidowych widoków) – rejestracja polega na tym, obserwatorzy zaczynają nasłuchiwać/czekać na wiadomość, • publikujemy wiadomość za pomocą Messengera (np. DialogMessage) – w chwili publikacji wszyscy aktualnie zarejestrowani obserwatorzy obsłużą akcje powiązaną z wiadomością. Opublikować wiadomość jesteśmy w stanie w projekcie Portable – nie zawiera to bowiem żadnego z API powiązanego z platformą. W przykładowym projekcie dołączonym do prezentacji w ten sposób zaimplementowane jest wyświetlanie Toastów (SnackBara), Dialogów oraz blokowanie interfejsu użytkownika przy operacji asynchronicznej.
  • 11. Kolejnym z widoków przedstawionym w aplikacji jest widok prostej listy zawierającej dane jak: • Imię • Nazwisko • Avatar W Xamarinie najłatwiejszym sposobem na zaimplementowanie widoków z listami jest „podpięcie się” pod kolekcję implementująca interfejs INotifyCollectionChanged (np. ObservableCollection<T>). Przy zmianie pozycji/usunięciu/dodaniu elementu listy propagowany jest event zadeklarowany w interfejsie INotifyCollectionChanged (CollectionChanged). Przy każdej zmianie kolekcji event ten zawiera informację o tym w jaki sposób zmieniła się lista. Niestety – poprawna implementacja list przy użyciu INotifyCollectionChanged jest problematyczna. RX+DYNAMICDATA, A OBSERVABLECOLLECTION. WPROWADZENIE DO LIST DANYCH
  • 12. Wszystkie algorytmy (jak na przykład sortowanie) musielibyśmy napisać samodzielnie - tak aby w poprawny sposób został propagowany event CollectionChanged. Dodatkowo – wszystkie operacje na ObservableCollection są wywoływane na głównym wątku interfejsu – gdy spróbujemy to zrobić na innym wątku aplikacja rzuci nam wyjątkiem. Z pomocą przychodzi nam RX (Reactive Extensions) oraz biblioteka DynamicData, która jest w stanie wykonać za nas całą pracę – tj. między innymi posortować, pogrupować dane na innych wątkach. Temat RX/DynamicData moglibyśmy omawiać tygodniami – toteż jest to tylko krótkie wprowadzenie do tematu. DynamicData jest biblioteką, która jest w stanie na podstawie: źródła danych i serii zadeklarowanych transformacji (w stylu posortuj, pogrupuj, „przetransformuj” model) utworzyć ReadOnlyObservableCollection<>, która będzie „propagowała” eventy CollectionChanged przy każdej z zadeklarowanych transformacji. Dzięki prawidłowej propagacji eventu CollectionChanged nasze listy mogą reagować na każdą ze zmian animacją.
  • 13. RX+DYNAMICDATA, A OBSERVABLECOLLECTION. WPROWADZENIE DO LIST DANYCH Aktualnie jedyną „słuszną” kontrolką do list w Androidzie jest RecyclerView. Listy wykonane przy użyciu RecyclerView tworzą tylko n widocznych widoków, które są następnie „reużywane” (tzw. View recycling – stąd nazwa RecyclerView). Dzięki takiemu rozwiązaniu aplikacje oparte na RecyclerView są wydajniejsze, zajmują mniej pamięci. W świecie „Java-Android” czy Xamarina bez MvvmCross aby wyświetlić listę musimy zaimplementować tzw. RecyclerAdapter – adapter, który wie skąd pobrać dane, ile ich jest, informujący RecylerView kiedy i gdzie zmienił się jakiś element na liście. MvvmCross załatwia to za programistę wystarczy dodać paczkę MvvmCross.Support.V7.RecyclerView. Na kolejnych slajdach zostaną przedstawione funkcjonalności RecyclerView opakowane przez MvvmCross.
  • 14. Utworzenie prostej listy z 1 typem elementów wymaga dodania bindingów do źródła danych (ItemsSource) oraz zdefiniowania atrybutu MvxItemTemplate, który powinien wskazywać na „layout” opisujący element listy. NAJPROSTSZA LISTA PRZY UŻYCIU MVXRECYCLERVIEW
  • 15. LISTA ZE WSPARCIEM RÓŻNYCH LAYOUTÓW - MVXITEMTEMPLATESELECTOR Bazując na funkcjonalności znanej z Windows Phone/WPF, swego czasu do MvvmCross dorzuciłem funkcjonalność zwaną „MvxItemTemplateSelector”. Dzięki temu dla jednej listy jesteśmy w stanie łatwo zdefiniować różne layouty dla jej elementów. Aby skorzystać z tej funkcjonalności do atrybutu „MvxTemplateSelector” należy wrzucić string, którego wartość to: „Namespace.TemplateSelectorClassName, AssemblyName” Należy zaimplementować MvxTemplateSelector. Zaimplementowane metody służą do wyboru layoutu w zależności od danego elementy listy.
  • 16. GRUPOWANIE A MVXRECYCLERVIEW Niedawno do funkcjonalności MvxRecyclerView dodałem możliwość grupowania listy. Funkcjonalność jest jak do tej pory dostępna jedynie w paczkach „unstable”. Aby dodać grupowanie do poprzedniej listy: Należy dodać atrybut MvxGroupedDataConverter analogicznie do MvxTemplateSelector. Należy określić layout „headera” grupy za pomocą atrybutu MvxGroupSectionLayoutId. Należy zaimplementować interfejs IMvxGroupedDataConverter, który na podstawie elementu listy powinien utworzyć obiekt MvxGroupedData.
  • 17. HEADER/FOOTER - MVXRECYCLERVIEW Kolejną z funkcjonalności list, którą dodałem do MvvmCross, jest obsługa Header/Footer list. Aby dodać header/footer do poprzedniego przykładu: Header/Footer definiujemy za pomocą przekazania layoutu do atrybutów: • MvxHeaderLayoutId, • MvxFooterLayoutId. Dodatkowo możemy wykorzystać: • MvxHidesHeaderIfEmpty, • MvxHidesFooterIfEmpty. To atrybuty, które ukrywają header/footer, gdy lista jest pusta.
  • 18. DZIĘKUJĘ ZA UWAGĘ! PRZEMYSŁAW RACIBORSKI In’saneLab Xamarin Developer