Analiza przypadku aplikacji międzyplatformowych: Zadanie
Tasky Portable to prosta aplikacja listy zadań do wykonania. W tym dokumencie omówiono sposób projektowania i tworzenia, postępując zgodnie ze wskazówkami dokumentu Building Cross-Platform Applications (Tworzenie aplikacji międzyplatformowych). Omówienie obejmuje następujące obszary:
Proces projektowania
Zaleca się utworzenie planu dla tego, co chcesz osiągnąć przed rozpoczęciem kodowania. Jest to szczególnie istotne w przypadku programowania międzyplatformowego, w którym tworzysz funkcje, które będą udostępniane na wiele sposobów. Począwszy od jasnego pomysłu na to, co tworzysz, oszczędza czas i nakład pracy w dalszej części cyklu programowania.
Wymagania
Pierwszym krokiem projektowania aplikacji jest zidentyfikowanie żądanych funkcji. Mogą to być cele wysokiego poziomu lub szczegółowe przypadki użycia. Zadanie ma proste wymagania funkcjonalne:
- Wyświetlanie listy zadań
- Dodawanie, edytowanie i usuwanie zadań
- Ustaw stan zadania na "gotowe"
Należy rozważyć użycie funkcji specyficznych dla platformy. Czy tasky może korzystać z geofencingu systemu iOS lub kafelków Windows Phone Live? Nawet jeśli nie używasz funkcji specyficznych dla platformy w pierwszej wersji, należy zaplanować z wyprzedzeniem, aby upewnić się, że warstwy danych biznesowych i danych mogą je pomieścić.
Projekt interfejsu użytkownika
Zacznij od projektu wysokiego poziomu, który można zaimplementować na platformach docelowych. Zanotuj ograniczenia interfejsu użytkownika o specyfikacji platformy. Na przykład w TabBarController
systemie iOS może być wyświetlanych więcej niż pięć przycisków, natomiast odpowiednik systemu Windows Phone może wyświetlać maksymalnie cztery.
Rysuj przepływ ekranu przy użyciu wybranego narzędzia (działa papier).
model danych
Wiedza na temat danych, które należy przechowywać, pomoże określić, który mechanizm trwałości ma być używany. Zobacz Dostęp do danych międzyplatformowych, aby uzyskać informacje na temat dostępnych mechanizmów magazynowania i pomóc w podejmowaniu między nimi decyzji. W tym projekcie będziemy używać SQLite.NET.
Zadanie musi przechowywać trzy właściwości dla każdego elementu TaskItem:
- Name — ciąg
- Uwagi — ciąg
- Gotowe — wartość logiczna
Podstawowe funkcje
Należy wziąć pod uwagę interfejs API, z którego interfejs użytkownika będzie musiał korzystać, aby spełnić wymagania. Lista zadań do wykonania wymaga następujących funkcji:
- Wyświetl listę wszystkich zadań — aby wyświetlić listę ekranów głównych wszystkich dostępnych zadań
- Pobierz jedno zadanie — po dotknięciu wiersza zadania
- Zapisz jedno zadanie — gdy zadanie jest edytowane
- Usuwanie jednego zadania — po usunięciu zadania
- Tworzenie pustego zadania — po utworzeniu nowego zadania
Aby można było ponownie użyć kodu, ten interfejs API należy zaimplementować raz w przenośnej bibliotece klas.
Implementacja
Po uzgodnieniu projektu aplikacji zastanów się, jak można ją zaimplementować jako aplikację międzyplatformową. Stanie się to architekturą aplikacji. Zgodnie ze wskazówkami zawartymi w dokumencie Building Cross-Platform Applications (Tworzenie aplikacji międzyplatformowych) kod aplikacji powinien zostać podzielony na następujące części:
- Wspólny kod — wspólny projekt, który zawiera kod umożliwiający ponowne użycie do przechowywania danych zadania; uwidacznianie klasy modelu i interfejsu API w celu zarządzania zapisywaniem i ładowaniem danych.
- Kod specyficzny dla platformy — projekty specyficzne dla platformy, które implementują natywny interfejs użytkownika dla każdego systemu operacyjnego, używając wspólnego kodu jako "zaplecza".
Te dwie części opisano w poniższych sekcjach.
Wspólny kod (PCL)
Tasky Portable używa strategii biblioteki klas przenośnych do udostępniania wspólnego kodu. Aby zapoznać się z opisem opcji udostępniania kodu, zobacz dokument Sharing Code Options (Opcje udostępniania kodu).
Cały wspólny kod, w tym warstwa dostępu do danych, kod bazy danych i kontrakty, jest umieszczany w projekcie biblioteki.
Kompletny projekt PCL przedstawiono poniżej. Cały kod w bibliotece przenośnej jest zgodny z każdą platformą docelową. Po wdrożeniu każda aplikacja natywna będzie odwoływać się do tej biblioteki.
Na poniższym diagramie klas przedstawiono klasy pogrupowane według warstwy. Klasa SQLiteConnection
jest standardowy kod z pakietu Sqlite-NET. Pozostałe klasy to niestandardowy kod zadania. Klasy TaskItemManager
i TaskItem
reprezentują interfejs API, który jest udostępniany aplikacjom specyficznym dla platformy.
Oddzielenie warstw przy użyciu przestrzeni nazw ułatwia zarządzanie odwołaniami między poszczególnymi warstwami. Projekty specyficzne dla platformy powinny zawierać tylko instrukcję using
dla warstwy biznesowej. Warstwa dostępu do danych i warstwa danych powinny być hermetyzowane przez interfejs API uwidoczniony TaskItemManager
w warstwie biznesowej.
Informacje
Przenośne biblioteki klas muszą być używane na wielu platformach, z których każda ma różne poziomy obsługi funkcji platformy i platformy. W związku z tym istnieją ograniczenia dotyczące pakietów i bibliotek platformy, których można używać. Na przykład platforma Xamarin.iOS nie obsługuje słowa kluczowego c# dynamic
, więc przenośna biblioteka klas nie może używać żadnego pakietu zależnego od kodu dynamicznego, mimo że taki kod będzie działać w systemie Android. Visual Studio dla komputerów Mac uniemożliwi dodawanie niezgodnych pakietów i odwołań, ale należy pamiętać o ograniczeniach, aby uniknąć niespodzianek później.
Uwaga: Zobaczysz, że biblioteki platform odwołań do projektów, których nie użyto. Te odwołania są uwzględniane jako część szablonów projektów platformy Xamarin. Po skompilowaniu aplikacji proces łączenia spowoduje usunięcie nieużywanego kodu, więc mimo System.Xml
odwołania nie zostanie on uwzględniony w końcowej aplikacji, ponieważ nie używamy żadnych funkcji Xml.
Warstwa danych (DL)
Warstwa danych zawiera kod, który wykonuje fizyczny magazyn danych — zarówno do bazy danych, plików prostych, jak i innych mechanizmów. Warstwa danych Tasky składa się z dwóch części: biblioteki SQLite-NET i kodu niestandardowego dodanego do połączenia.
Zadanie opiera się na pakiecie NuGet Sqlite-net (opublikowanym przez Franka Kruegera) w celu osadzenia kodu SQLite-NET, który udostępnia interfejs bazy danych mapowania obiektów (ORM). Klasa TaskItemDatabase
dziedziczy SQLiteConnection
i dodaje wymagane metody Create, Read, Update, Delete (CRUD), aby odczytywać i zapisywać dane w sqlite. Jest to prosta implementacja standardowych metod CRUD, które mogą być ponownie używane w innych projektach.
Element TaskItemDatabase
jest pojedynczym elementem zapewniającym, że cały dostęp występuje względem tego samego wystąpienia. Blokada służy do zapobiegania równoczesnym dostępowi z wielu wątków.
SQLite w systemie Windows Phone
Chociaż systemy iOS i Android są dostarczane z sqLite w ramach systemu operacyjnego, system Windows Phone nie zawiera zgodnego aparatu bazy danych. Aby udostępnić kod na wszystkich trzech platformach, wymagana jest natywna dla systemu Windows wersja SQLite. Aby uzyskać więcej informacji na temat konfigurowania projektu systemu Windows Phone dla usługi Sqlite, zobacz Praca z lokalną bazą danych .
Używanie interfejsu do uogólniania dostępu do danych
Warstwa danych przyjmuje zależność, BL.Contracts.IBusinessIdentity
aby mogła implementować abstrakcyjne metody dostępu do danych, które wymagają klucza podstawowego. Każda klasa warstwy biznesowej, która implementuje interfejs, może być utrwalana w warstwie danych.
Interfejs określa tylko właściwość liczby całkowitej, która będzie działać jako klucz podstawowy:
public interface IBusinessEntity {
int ID { get; set; }
}
Klasa bazowa implementuje interfejs i dodaje atrybuty SQLite-NET, aby oznaczyć je jako automatycznie zwiększający klucz podstawowy. Każda klasa w warstwie biznesowej, która implementuje tę klasę bazową, może być utrwalana w warstwie danych:
public abstract class BusinessEntityBase : IBusinessEntity {
public BusinessEntityBase () {}
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
}
Przykładem metod ogólnych w warstwie danych używającej interfejsu jest następująca GetItem<T>
metoda:
public T GetItem<T> (int id) where T : BL.Contracts.IBusinessEntity, new ()
{
lock (locker) {
return Table<T>().FirstOrDefault(x => x.ID == id);
}
}
Blokowanie w celu uniemożliwienia dostępu współbieżnego
Blokada jest implementowana w klasie, TaskItemDatabase
aby uniemożliwić współbieżny dostęp do bazy danych. Ma to na celu zapewnienie, że współbieżny dostęp z różnych wątków jest serializowany (w przeciwnym razie składnik interfejsu użytkownika może próbować odczytać bazę danych w tym samym czasie, gdy wątek w tle jest aktualizowany). Przykład implementacji blokady przedstawiono tutaj:
static object locker = new object ();
public IEnumerable<T> GetItems<T> () where T : BL.Contracts.IBusinessEntity, new ()
{
lock (locker) {
return (from i in Table<T> () select i).ToList ();
}
}
public T GetItem<T> (int id) where T : BL.Contracts.IBusinessEntity, new ()
{
lock (locker) {
return Table<T>().FirstOrDefault(x => x.ID == id);
}
}
Większość kodu warstwy danych może być ponownie używana w innych projektach. Jedynym kodem specyficznym dla aplikacji w warstwie jest CreateTable<TaskItem>
wywołanie w konstruktorze TaskItemDatabase
.
Warstwa dostępu do danych (DAL)
Klasa TaskItemRepository
hermetyzuje mechanizm przechowywania danych za pomocą silnie typizowanego interfejsu API, który umożliwia TaskItem
tworzenie, usuwanie, pobieranie i aktualizowanie obiektów.
Korzystanie z kompilacji warunkowej
Klasa używa kompilacji warunkowej do ustawiania lokalizacji pliku — jest to przykład implementacji rozbieżności platformy. Właściwość zwracająca ścieżkę kompiluje się do innego kodu na każdej platformie. W tym miejscu przedstawiono dyrektywy kompilatora kodu i kompilatora specyficzne dla platformy:
public static string DatabaseFilePath {
get {
var sqliteFilename = "TaskDB.db3";
#if SILVERLIGHT
// Windows Phone expects a local path, not absolute
var path = sqliteFilename;
#else
#if __ANDROID__
// Just use whatever directory SpecialFolder.Personal returns
string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); ;
#else
// we need to put in /Library/ on iOS5.1+ to meet Apple's iCloud terms
// (they don't want non-user-generated data in Documents)
string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); // Documents folder
string libraryPath = Path.Combine (documentsPath, "..", "Library"); // Library folder
#endif
var path = Path.Combine (libraryPath, sqliteFilename);
#endif
return path;
}
}
W zależności od platformy dane wyjściowe będą mieć wartość "<app path>/Library/TaskDB.db3" dla systemu iOS, "<ścieżka> aplikacji/Documents/TaskDB.db3" dla systemu Android lub tylko "TaskDB.db3" dla systemu Windows Phone.
Warstwa biznesowa (BL)
Warstwa biznesowa implementuje klasy Model i fasadę do zarządzania nimi.
W obszarze Tasky model jest klasą TaskItem
i TaskItemManager
implementuje wzorzec fasady w celu zapewnienia interfejsu API do zarządzania TaskItems
.
Fasada
TaskItemManager
Opakowuje DAL.TaskItemRepository
metodę Get, Save and Delete, do których będą odwoływać się warstwy aplikacji i interfejsu użytkownika.
W razie potrzeby reguły biznesowe i logika zostaną umieszczone w tym miejscu — na przykład wszystkie reguły weryfikacji, które muszą zostać spełnione przed zapisaniem obiektu.
Interfejs API dla kodu specyficznego dla platformy
Po napisaniu wspólnego kodu interfejs użytkownika musi zostać skompilowany w celu zbierania i wyświetlania danych udostępnianych przez nie. Klasa TaskItemManager
implementuje wzorzec fasady, aby zapewnić prosty interfejs API dla kodu aplikacji w celu uzyskania dostępu.
Kod napisany w każdym projekcie specyficznym dla platformy będzie zwykle ściśle powiązany z natywnym zestawem SDK tego urządzenia i uzyskuje dostęp tylko do wspólnego kodu przy użyciu interfejsu API zdefiniowanego TaskItemManager
przez . Obejmuje to metody i klasy biznesowe, które uwidacznia, takie jak TaskItem
.
Obrazy nie są udostępniane między platformami, ale dodawane niezależnie do każdego projektu. Jest to ważne, ponieważ każda platforma obsługuje obrazy inaczej, używając różnych nazw plików, katalogów i rozwiązań.
W pozostałych sekcjach omówiono szczegóły implementacji specyficzne dla platformy interfejsu użytkownika zadania.
Aplikacja systemu iOS
Istnieje tylko kilka klas wymaganych do zaimplementowania aplikacji Tasky systemu iOS przy użyciu wspólnego projektu PCL do przechowywania i pobierania danych. Pełny projekt platformy Xamarin.iOS dla systemu iOS jest pokazany poniżej:
Klasy są wyświetlane na tym diagramie pogrupowane w warstwy.
Informacje
Aplikacja systemu iOS odwołuje się do bibliotek zestawu SDK specyficznych dla platformy — np. Xamarin.iOS i MonoTouch.Dialog-1.
Musi również odwoływać się do TaskyPortableLibrary
projektu PCL.
Lista odwołań jest wyświetlana tutaj:
Warstwa aplikacji i warstwa interfejsu użytkownika są implementowane w tym projekcie przy użyciu tych odwołań.
Warstwa aplikacji (AL)
Warstwa aplikacji zawiera klasy specyficzne dla platformy wymagane do powiązania obiektów uwidocznionych przez PCL z interfejsem użytkownika. Aplikacja specyficzna dla systemu iOS ma dwie klasy ułatwiające wyświetlanie zadań:
- EditingSource — ta klasa służy do wiązania list zadań z interfejsem użytkownika. Ponieważ
MonoTouch.Dialog
została użyta na liście Zadań, musimy zaimplementować ten pomocnik, aby włączyć funkcję szybkiego przesunięcia do usunięcia w elemecieUITableView
. Szybkie przesunięcie do usunięcia jest powszechne w systemie iOS, ale nie w systemie Android lub Windows Phone, więc konkretny projekt systemu iOS jest jedynym, który go implementuje. - TaskDialog — ta klasa służy do powiązania pojedynczego zadania z interfejsem użytkownika. Używa interfejsu
MonoTouch.Dialog
API odbicia do zawijaniaTaskItem
obiektu z klasą zawierającą poprawne atrybuty, aby umożliwić poprawne formatowanie ekranu wejściowego.
Klasa TaskDialog
używa MonoTouch.Dialog
atrybutów do utworzenia ekranu na podstawie właściwości klasy. Klasa wygląda następująco:
public class TaskDialog {
public TaskDialog (TaskItem task)
{
Name = task.Name;
Notes = task.Notes;
Done = task.Done;
}
[Entry("task name")]
public string Name { get; set; }
[Entry("other task info")]
public string Notes { get; set; }
[Entry("Done")]
public bool Done { get; set; }
[Section ("")]
[OnTap ("SaveTask")] // method in HomeScreen
[Alignment (UITextAlignment.Center)]
public string Save;
[Section ("")]
[OnTap ("DeleteTask")] // method in HomeScreen
[Alignment (UITextAlignment.Center)]
public string Delete;
}
Zwróć uwagę, że OnTap
atrybuty wymagają nazwy metody — te metody muszą istnieć w klasie, w której MonoTouch.Dialog.BindingContext
jest tworzona (w tym przypadku HomeScreen
klasa omówiona w następnej sekcji).
Warstwa interfejsu użytkownika
Warstwa interfejsu użytkownika składa się z następujących klas:
- AppDelegate — zawiera wywołania interfejsu API wyglądu w celu stylu czcionek i kolorów używanych w aplikacji. Zadanie jest prostą aplikacją, więc nie ma innych zadań inicjowania uruchomionych w programie
FinishedLaunching
. - Ekrany — podklasy
UIViewController
definiujące każdy ekran i jego zachowanie. Ekrany łączą interfejs użytkownika z klasami warstw aplikacji i wspólnym interfejsem API (TaskItemManager
). W tym przykładzie ekrany są tworzone w kodzie, ale mogły zostać zaprojektowane przy użyciu konstruktora interfejsu Xcode lub projektanta scenorysu. - Obrazy — elementy wizualne są ważną częścią każdej aplikacji. Zadanie ma ekran powitalny i obrazy ikon, które dla systemu iOS muszą być dostarczane w regularnej rozdzielczości i Siatkówki.
Ekran główny
Ekran główny to MonoTouch.Dialog
ekran przedstawiający listę zadań z bazy danych SQLite. Dziedziczy i DialogViewController
implementuje kod, aby ustawić Root
obiekt w taki sposób, aby zawierał kolekcję TaskItem
obiektów do wyświetlenia.
Dwie główne metody związane z wyświetlaniem listy zadań i interakcją z nią są następujące:
- PopulateTable — używa metody warstwy
TaskManager.GetTasks
biznesowej do pobrania kolekcjiTaskItem
obiektów do wyświetlenia. - Selected — po dotknięciu wiersza zadanie zostanie wyświetlone na nowym ekranie.
Ekran szczegółów zadania
Szczegóły zadania to ekran wejściowy, który umożliwia edytowanie lub usuwanie zadań.
Funkcja Tasky używa MonoTouch.Dialog
interfejsu API odbicia do wyświetlania ekranu, więc nie UIViewController
ma implementacji. HomeScreen
Zamiast tego klasa tworzy wystąpienie i wyświetla klasę używającą DialogViewController
TaskDialog
z warstwy aplikacji.
Ten zrzut ekranu przedstawia pusty ekran przedstawiający ustawienie atrybutu Entry
tekstu znaku wodnego w polach Nazwa i Uwagi :
Funkcjonalność ekranu Szczegóły zadania (na przykład zapisywanie lub usuwanie zadania) musi być zaimplementowana w HomeScreen
klasie, ponieważ jest to miejsce, w którym MonoTouch.Dialog.BindingContext
jest tworzony. HomeScreen
Następujące metody obsługują ekran Szczegóły zadania:
- ShowTaskDetails — tworzy obiekt
MonoTouch.Dialog.BindingContext
, aby renderować ekran. Tworzy ekran wejściowy przy użyciu odbicia w celu pobrania nazw właściwości i typów zTaskDialog
klasy. Dodatkowe informacje, takie jak tekst znaku wodnego dla pól wejściowych, są implementowane z atrybutami we właściwościach. - SaveTask — ta metoda jest przywołynięta w
TaskDialog
klasie za pośrednictwem atrybutuOnTap
. Jest on wywoływany po naciśnięciu Zapisz i używa elementu ,MonoTouch.Dialog.BindingContext
aby pobrać dane wprowadzone przez użytkownika przed zapisaniem zmian przy użyciu poleceniaTaskItemManager
. - DeleteTask — ta metoda jest przywoływała się w
TaskDialog
klasie za pośrednictwem atrybutuOnTap
. UżywaTaskItemManager
ich do usuwania danych przy użyciu klucza podstawowego (właściwości ID).
Aplikacja dla systemu Android
Kompletny projekt platformy Xamarin.Android został na zdjęciu poniżej:
Diagram klas z klasami pogrupowanych według warstwy:
Informacje
Projekt aplikacji systemu Android musi odwoływać się do zestawu Xamarin.Android specyficznego dla platformy, aby uzyskać dostęp do klas z zestawu Android SDK.
Musi również odwoływać się do projektu PCL (np. TaskyPortableLibrary) w celu uzyskania dostępu do wspólnych danych i kodu warstwy biznesowej.
Warstwa aplikacji (AL)
Podobnie jak w przypadku wersji systemu iOS, którą omówiliśmy wcześniej, warstwa aplikacji w wersji systemu Android zawiera klasy specyficzne dla platformy wymagane do "powiązania" obiektów uwidocznionych przez core z interfejsem użytkownika.
TaskListAdapter — aby wyświetlić listę<T> obiektów, musimy zaimplementować adapter do wyświetlania obiektów niestandardowych w obiekcie ListView
. Karta steruje układem używanym dla każdego elementu na liście — w tym przypadku kod używa wbudowanego układu systemu SimpleListItemChecked
Android.
Interfejs użytkownika
Warstwa interfejsu użytkownika aplikacji systemu Android jest kombinacją kodu i znaczników XML.
- Resources/Layout — układy ekranu i projekt komórki wiersza zaimplementowany jako pliki AXML. Kod AXML można napisać ręcznie lub wizualnie za pomocą projektanta interfejsu użytkownika platformy Xamarin dla systemu Android.
- Resources/Drawable — obrazy (ikony) i przycisk niestandardowy.
- Ekrany — podklasy działań definiujące każdy ekran i jego zachowanie. Łączy interfejs użytkownika z klasami warstw aplikacji i wspólnym interfejsem API (
TaskItemManager
).
Ekran główny
Ekran główny składa się z podklasy HomeScreen
Activity i HomeScreen.axml
pliku, który definiuje układ (położenie przycisku i listy zadań). Ekran wygląda następująco:
Kod ekranu głównego definiuje programy obsługi służące do klikania przycisku i klikania elementów na liście, a także wypełniania listy w metodzie OnResume
(tak aby odzwierciedlały zmiany wprowadzone na ekranie szczegółów zadania). Dane są ładowane przy użyciu warstwy TaskItemManager
biznesowej i TaskListAdapter
warstwy aplikacji.
Ekran szczegółów zadania
Ekran szczegółów zadania składa się również z Activity
podklasy i pliku układu AXML. Układ określa lokalizację kontrolek wejściowych, a klasa C# definiuje zachowanie ładowania i zapisywania TaskItem
obiektów.
Wszystkie odwołania do biblioteki PCL są za pośrednictwem TaskItemManager
klasy .
Aplikacja systemu Windows Phone
Kompletny projekt systemu Windows Phone:
Na poniższym diagramie przedstawiono klasy pogrupowane w warstwy:
Informacje
Projekt specyficzny dla platformy musi odwoływać się do wymaganych bibliotek specyficznych dla platformy (takich jak Microsoft.Phone
i System.Windows
), aby utworzyć prawidłową aplikację systemu Windows Phone.
Musi również odwoływać się do projektu PCL (np. TaskyPortableLibrary
) w celu korzystania z TaskItem
klasy i bazy danych.
Warstwa aplikacji (AL)
Ponownie, podobnie jak w przypadku wersji systemów iOS i Android, warstwa aplikacji składa się z elementów innych niż wizualne, które ułatwiają powiązanie danych z interfejsem użytkownika.
Modele widoków
Modele ViewModel zawierają dane z PCL ( TaskItemManager
) i przedstawiają je w sposób, który może być używany przez powiązanie danych Silverlight/XAML. Jest to przykład zachowania specyficznego dla platformy (zgodnie z opisem w dokumencie Aplikacje międzyplatformowe).
Interfejs użytkownika
Język XAML ma unikatową funkcję powiązania danych, którą można zadeklarować w znacznikach i zmniejszyć ilość kodu wymaganego do wyświetlania obiektów:
- Pages — pliki XAML i ich kodbehind definiują interfejs użytkownika i odwołują się do modelu ViewModels oraz projektu PCL do wyświetlania i zbierania danych.
- Obrazy — ekran powitalny, obrazy tła i ikon są kluczowym elementem interfejsu użytkownika.
Strona główna
Klasa MainPage używa klasy TaskListViewModel
do wyświetlania danych przy użyciu funkcji powiązania danych XAML. DataContext
Strona jest ustawiona na model widoku, który jest wypełniany asynchronicznie. Składnia {Binding}
w języku XAML określa sposób wyświetlania danych.
TaskDetailsPage
Każde zadanie jest wyświetlane przez powiązanie elementu TaskViewModel
z XAML zdefiniowanym w pliku TaskDetailsPage.xaml. Dane zadania są pobierane za pośrednictwem TaskItemManager
elementu w warstwie biznesowej.
Wyniki
Wynikowe aplikacje wyglądają następująco na każdej platformie:
iOS
Aplikacja używa standardowego projektu interfejsu użytkownika systemu iOS, takiego jak przycisk "Dodaj" umieszczony na pasku nawigacyjnym i używając wbudowanej ikony plusa (+). Używa również domyślnego UINavigationController
zachowania przycisku "Wstecz" i obsługuje polecenie "swipe-to-delete" w tabeli.
Android
Aplikacja systemu Android używa wbudowanych kontrolek, w tym wbudowanego układu wierszy, które wymagają wyświetlenia "znacznika". Zachowanie zaplecza sprzętu/systemu jest obsługiwane oprócz przycisku wstecz na ekranie.
Windows Phone
Aplikacja systemu Windows Phone używa standardowego układu, wypełniając pasek aplikacji u dołu ekranu zamiast paska nawigacyjnego u góry.
Podsumowanie
Ten dokument zawiera szczegółowe wyjaśnienie sposobu stosowania zasad projektowania aplikacji warstwowych do prostej aplikacji w celu ułatwienia ponownego użycia kodu na trzech platformach mobilnych: iOS, Android i Windows Phone.
Opisał on proces używany do projektowania warstw aplikacji i omawiał, jakie funkcje i kod zostały zaimplementowane w każdej warstwie.
Kod można pobrać z usługi github.