Freigeben über


Plattformübergreifende App-Fallstudie: Tasky

Tasky Portable ist eine einfache Aufgabenlistenanwendung. In diesem Dokument wird erläutert, wie es entworfen und erstellt wurde, und zwar im Anschluss an die Anleitung des Dokuments "Plattformübergreifende Anwendungen erstellen" . Die Diskussion behandelt die folgenden Bereiche:

Entwurfsprozess

Es ist ratsam, eine Straßenkarte für das zu erstellen, was Sie erreichen möchten, bevor Sie mit dem Codieren beginnen. Dies gilt insbesondere für plattformübergreifende Entwicklung, bei der Sie Funktionen erstellen, die auf mehrere Arten verfügbar gemacht werden. Beginnend mit einer klaren Vorstellung davon, was Sie erstellen, spart Später im Entwicklungszyklus Zeit und Aufwand.

Anforderungen

Der erste Schritt beim Entwerfen einer Anwendung besteht darin, die gewünschten Features zu identifizieren. Hierbei kann es sich um allgemeine Ziele oder detaillierte Anwendungsfälle handelt. Tasky hat einfache funktionale Anforderungen:

  • Anzeigen einer Liste von Aufgaben
  • Hinzufügen, Bearbeiten und Löschen von Aufgaben
  • Festlegen des Status eines Vorgangs auf "Fertig"

Sie sollten die Verwendung plattformspezifischer Features in Betracht ziehen. Können Tasky iOS-Geofencing- oder Windows Phone Live-Kacheln nutzen? Auch wenn Sie in der ersten Version keine plattformspezifischen Features verwenden, sollten Sie vorausplanen, um sicherzustellen, dass Ihre Geschäfts- und Datenebenen diese berücksichtigen können.

Benutzeroberflächendesign

Beginnen Sie mit einem allgemeinen Design, das auf den Zielplattformen implementiert werden kann. Achten Sie darauf, plattformspezifische UI-Einschränkungen zu beachten. Beispielsweise kann ein TabBarController iOS mehr als fünf Schaltflächen anzeigen, während das Windows Phone-Äquivalent bis zu vier anzeigen kann. Zeichnen Sie den Bildschirmfluss mithilfe des Tools Ihrer Wahl (Papierarbeiten).

Zeichnen Sie den Bildschirmfluss mithilfe des Tools Ihrer Wahlpapierarbeiten.

Datenmodell

Wenn Sie wissen, welche Daten gespeichert werden müssen, können Sie bestimmen, welcher Persistenzmechanismus verwendet werden soll. Unter Plattformübergreifender Datenzugriff finden Sie Informationen zu den verfügbaren Speichermechanismen und helfen bei der Entscheidung zwischen ihnen. Für dieses Projekt verwenden wir SQLite.NET.

Tasky muss drei Eigenschaften für jedes "TaskItem"-Objekt speichern:

  • Name – Zeichenfolge
  • Notizen – Zeichenfolge
  • Fertig – Boolescher Wert

Kernfunktionalität

Berücksichtigen Sie die API, die die Benutzeroberfläche nutzen muss, um die Anforderungen zu erfüllen. Für eine Aufgabenliste sind die folgenden Funktionen erforderlich:

  • Alle Aufgaben auflisten – um die Hauptbildschirmliste aller verfügbaren Aufgaben anzuzeigen
  • Abrufen einer Aufgabe – wenn eine Aufgabenzeile berührt wird
  • Speichern einer Aufgabe – wenn eine Aufgabe bearbeitet wird
  • Löschen einer Aufgabe – wenn eine Aufgabe gelöscht wird
  • Erstellen einer leeren Aufgabe – wenn eine neue Aufgabe erstellt wird

Um die Codewiederverwendung zu erreichen, sollte diese API einmal in der portablen Klassenbibliothek implementiert werden.

Implementierung

Nachdem das Anwendungsdesign vereinbart wurde, überlegen Sie, wie sie als plattformübergreifende Anwendung implementiert werden kann. Dies wird zur Architektur der Anwendung. Im Anschluss an die Anleitung im Dokument "Plattformübergreifende Anwendungen erstellen" sollte der Anwendungscode in die folgenden Teile unterteilt werden:

  • Common Code – ein gängiges Projekt, das wiederverwendbaren Code zum Speichern der Vorgangsdaten enthält; eine Model-Klasse und eine API zum Verwalten des Speicherns und Ladens von Daten verfügbar machen.
  • Plattformspezifischer Code – plattformspezifische Projekte, die eine systemeigene Benutzeroberfläche für jedes Betriebssystem implementieren, wobei der gemeinsame Code als "Back-End" verwendet wird.

Plattformspezifische Projekte implementieren eine systemeigene Benutzeroberfläche für jedes Betriebssystem, wobei der gemeinsame Code als Back-End verwendet wird.

Diese beiden Teile werden in den folgenden Abschnitten beschrieben.

Allgemeiner Code (PCL)

Tasky Portable verwendet die Portable Class Library-Strategie zum Freigeben von gemeinsamem Code. Eine Beschreibung der Codefreigabeoptionen finden Sie im Dokument "Freigabecodeoptionen ".

Der gesamte gemeinsame Code, einschließlich datenzugriffsebene, Datenbankcode und Verträge, wird im Bibliotheksprojekt platziert.

Das vollständige PCL-Projekt ist unten dargestellt. Der gesamte Code in der portablen Bibliothek ist mit jeder zielbezogenen Plattform kompatibel. Bei der Bereitstellung referenziert jede systemeigene App auf diese Bibliothek.

Bei der Bereitstellung referenziert jede systemeigene App auf diese Bibliothek.

Das folgende Klassendiagramm zeigt die Klassen nach Ebene gruppiert. Die SQLiteConnection Klasse ist Codebausteine aus dem Sqlite-NET-Paket. Die restlichen Klassen sind benutzerdefinierter Code für Tasky. Die TaskItemManager klassen TaskItem stellen die API dar, die für die plattformspezifischen Anwendungen verfügbar gemacht wird.

Die Klassen TaskItemManager und TaskItem stellen die API dar, die für die plattformspezifischen Anwendungen verfügbar gemacht wird.

Die Verwendung von Namespaces zum Trennen der Ebenen hilft beim Verwalten von Verweisen zwischen den einzelnen Ebenen. Die plattformspezifischen Projekte sollten nur eine using Anweisung für die Business Layer enthalten. Die Datenzugriffsschicht und die Datenebene sollten von der API gekapselt werden, die von TaskItemManager der Geschäftsebene verfügbar gemacht wird.

References

Portable Klassenbibliotheken müssen auf mehreren Plattformen verwendet werden können, wobei jeweils unterschiedliche Unterstützungsebenen für Plattform- und Frameworkfeatures gelten. Aus diesem Hintergrund gibt es Einschränkungen dafür, welche Pakete und Frameworkbibliotheken verwendet werden können. Beispielsweise unterstützt Xamarin.iOS das c# dynamic -Schlüsselwort nicht, sodass eine portable Klassenbibliothek kein Paket verwenden kann, das von dynamischem Code abhängt, obwohl dieser Code unter Android funktioniert. Visual Studio für Mac verhindern, dass Sie inkompatible Pakete und Verweise hinzufügen, aber Sie sollten Einschränkungen beachten, um Überraschungen später zu vermeiden.

Hinweis: Ihre Projekte verweisen auf Frameworkbibliotheken, die Sie nicht verwendet haben. Diese Verweise werden als Teil der Xamarin-Projektvorlagen eingeschlossen. Wenn Apps kompiliert werden, entfernt der Verknüpfungsprozess nicht referenzierten Code. System.Xml Obwohl darauf verwiesen wurde, wird er nicht in die endgültige Anwendung einbezogen, da wir keine XML-Funktionen verwenden.

Data Layer (DL)

Die Datenschicht enthält den Code, mit dem die physische Speicherung von Daten ausgeführt wird – unabhängig davon, ob es sich um eine Datenbank, flat files oder einen anderen Mechanismus handelt. Die Tasky-Datenschicht besteht aus zwei Teilen: der SQLite-NET-Bibliothek und dem benutzerdefinierten Code, der zum Verknüpfen hinzugefügt wurde.

Tasky basiert auf dem Sqlite-net NuGet-Paket (veröffentlicht von Frank Krueger), um SQLite-NET-Code einzubetten, der eine Object-Relational Mapping (ORM)-Datenbankschnittstelle bereitstellt. Die TaskItemDatabase Klasse erbt von SQLiteConnection und fügt die erforderlichen Create-, Read-, Update-, Delete -, Delete (CRUD)-Methoden zum Lesen und Schreiben von Daten in SQLite hinzu. Es handelt sich um eine einfache Textbausteineimplementierung generischer CRUD-Methoden, die in anderen Projekten wiederverwendet werden können.

Dies TaskItemDatabase ist ein Singleton, der sicherstellt, dass der gesamte Zugriff für dieselbe Instanz erfolgt. Eine Sperre wird verwendet, um den gleichzeitigen Zugriff von mehreren Threads zu verhindern.

SQLite unter Windows Phone

Während iOS und Android beide als Teil des Betriebssystems mit SQLite ausgeliefert werden, enthält Windows Phone kein kompatibles Datenbankmodul. Um Code auf allen drei Plattformen freizugeben, ist eine systemeigene Windows-Version von SQLite erforderlich. Weitere Informationen zum Einrichten Ihres Windows Phone-Projekts für Sqlite finden Sie unter Arbeiten mit einer lokalen Datenbank .

Verwenden einer Schnittstelle zum Generalisieren des Datenzugriffs

Die Datenschicht benötigt eine Abhängigkeit BL.Contracts.IBusinessIdentity , sodass sie abstrakte Datenzugriffsmethoden implementieren kann, die einen Primärschlüssel erfordern. Jede Business Layer-Klasse, die die Schnittstelle implementiert, kann dann in der Datenebene beibehalten werden.

Die Schnittstelle gibt lediglich eine ganzzahlige Eigenschaft an, die als Primärschlüssel fungiert:

public interface IBusinessEntity {
    int ID { get; set; }
}

Die Basisklasse implementiert die Schnittstelle und fügt die SQLite-NET-Attribute hinzu, um sie als automatisch inkrementierenden Primärschlüssel zu markieren. Jede Klasse in der Business Layer, die diese Basisklasse implementiert, kann dann in der Datenebene beibehalten werden:

public abstract class BusinessEntityBase : IBusinessEntity {
    public BusinessEntityBase () {}
    [PrimaryKey, AutoIncrement]
    public int ID { get; set; }
}

Ein Beispiel für die generischen Methoden in der Datenschicht, die die Schnittstelle verwenden, ist diese GetItem<T> Methode:

public T GetItem<T> (int id) where T : BL.Contracts.IBusinessEntity, new ()
{
    lock (locker) {
        return Table<T>().FirstOrDefault(x => x.ID == id);
    }
}

Sperren, um gleichzeitigen Zugriff zu verhindern

Eine Sperre wird innerhalb der TaskItemDatabase Klasse implementiert, um gleichzeitigen Zugriff auf die Datenbank zu verhindern. Dadurch wird sichergestellt, dass gleichzeitiger Zugriff aus verschiedenen Threads serialisiert wird (andernfalls kann eine UI-Komponente versuchen, die Datenbank gleichzeitig zu lesen, wenn ein Hintergrundthread aktualisiert wird). Hier sehen Sie ein Beispiel für die Implementierung der Sperre:

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);
    }
}

Der Großteil des Data Layer-Codes kann in anderen Projekten wiederverwendet werden. Der einzige anwendungsspezifische Code auf der Ebene ist der CreateTable<TaskItem> Aufruf im TaskItemDatabase Konstruktor.

Datenzugriffsebene (DAL)

Die TaskItemRepository Klasse kapselt den Datenspeichermechanismus mit einer stark typierten API, mit der Objekte erstellt, gelöscht, abgerufen und aktualisiert werden können TaskItem .

Verwenden der bedingten Kompilierung

Die Klasse verwendet die bedingte Kompilierung, um den Dateispeicherort festzulegen . Dies ist ein Beispiel für die Implementierung von Platform Divergence. Die Eigenschaft, die den Pfad zurückgibt, kompiliert in verschiedenen Code auf jeder Plattform. Die code- und plattformspezifischen Compilerdirektiven werden hier gezeigt:

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;
    }
}

Je nach Plattform lautet die Ausgabe "<App-Pfad>/Library/TaskDB.db3" für iOS, "<App-Pfad>/Dokumente/TaskDB.db3" für Android oder nur "TaskDB.db3" für Windows Phone.

Business Layer (BL)

Die Business Layer implementiert die Modellklassen und eine Fassade, um sie zu verwalten. In Tasky ist das Modell die TaskItem Klasse und TaskItemManager implementiert das Fassadenmuster, um eine API für die Verwaltung TaskItemsbereitzustellen.

Fassade

TaskItemManager umschließt die DAL.TaskItemRepository Methode "Get", "Save" und "Delete", auf die von den Anwendungs- und UI-Ebenen verwiesen wird.

Geschäftsregeln und Logik würden hier platziert, wenn erforderlich – z. B. alle Überprüfungsregeln, die erfüllt sein müssen, bevor ein Objekt gespeichert wird.

API für plattformspezifischen Code

Nachdem der gemeinsame Code geschrieben wurde, muss die Benutzeroberfläche erstellt werden, um die darin verfügbar gemachten Daten zu sammeln und anzuzeigen. Die TaskItemManager Klasse implementiert das Fassadenmuster, um eine einfache API für den Anwendungscode für den Zugriff bereitzustellen.

Der in jedem plattformspezifischen Projekt geschriebene Code wird in der Regel eng mit dem systemeigenen SDK dieses Geräts gekoppelt und nur auf den gemeinsamen Code mithilfe der durch die TaskItemManagerAPI definierten API zugreifen. Dazu gehören die Methoden und Geschäftsklassen, die sie verfügbar machen, z TaskItem. B. .

Bilder werden nicht plattformübergreifend freigegeben, sondern unabhängig zu jedem Projekt hinzugefügt. Dies ist wichtig, da jede Plattform Bilder unterschiedlich verarbeitet, wobei verschiedene Dateinamen, Verzeichnisse und Auflösungen verwendet werden.

In den verbleibenden Abschnitten werden die plattformspezifischen Implementierungsdetails der Tasky-Benutzeroberfläche erläutert.

iOS-App

Es sind nur eine Handvoll Klassen erforderlich, um die iOS Tasky-Anwendung mithilfe des allgemeinen PCL-Projekts zum Speichern und Abrufen von Daten zu implementieren. Das vollständige iOS Xamarin.iOS-Projekt wird unten gezeigt:

iOS-Projekt wird hier gezeigt

Die Klassen werden in diesem Diagramm dargestellt, gruppiert in Ebenen.

Die Klassen werden in diesem Diagramm dargestellt, gruppiert in Ebenen

References

Die iOS-App verweist auf die plattformspezifischen SDK-Bibliotheken – z. B. Xamarin.iOS und MonoTouch.Dialog-1.

Außerdem muss auf das TaskyPortableLibrary PCL-Projekt verwiesen werden. Die Liste der Verweise wird hier gezeigt:

Die Liste der Verweise wird hier angezeigt.

Die Application Layer- und User Interface Layer werden in diesem Projekt mithilfe dieser Verweise implementiert.

Application Layer (AL)

Die Anwendungsschicht enthält plattformspezifische Klassen, die zum "Binden" der objekte erforderlich sind, die von der PCL an die Benutzeroberfläche verfügbar gemacht werden. Die iOS-spezifische Anwendung verfügt über zwei Klassen zum Anzeigen von Aufgaben:

  • EditingSource – Diese Klasse wird verwendet, um Aufgabenlisten an die Benutzeroberfläche zu binden. Da MonoTouch.Dialog für die Aufgabenliste verwendet wurde, müssen wir diese Hilfsfunktion implementieren, um Wisch-zu-Löschen-Funktionen in der UITableView . Wisch-zu-Löschen ist in iOS üblich, aber nicht unter Android oder Windows Phone, sodass das iOS-spezifische Projekt der einzige ist, der es implementiert.
  • TaskDialog – Diese Klasse wird verwendet, um eine einzelne Aufgabe an die Benutzeroberfläche zu binden. Es verwendet die MonoTouch.Dialog Spiegelungs-API, um das TaskItem Objekt mit einer Klasse zu "umbrechen", die die richtigen Attribute enthält, damit der Eingabebildschirm ordnungsgemäß formatiert werden kann.

Die TaskDialog Klasse verwendet MonoTouch.Dialog Attribute, um einen Bildschirm basierend auf den Eigenschaften einer Klasse zu erstellen. Die Klasse sieht wie folgt aus:

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;
}

Beachten Sie, dass für die OnTap Attribute ein Methodenname erforderlich ist – diese Methoden müssen in der Klasse vorhanden sein, in der die MonoTouch.Dialog.BindingContext Klasse erstellt wird (in diesem Fall die HomeScreen im nächsten Abschnitt erläuterte Klasse).

Benutzeroberflächenebene (UI)

Die Benutzeroberfläche besteht aus den folgenden Klassen:

  1. AppDelegate – Enthält Aufrufe der Darstellungs-API zum Formatieren der Schriftarten und Farben, die in der Anwendung verwendet werden. Tasky ist eine einfache Anwendung, sodass keine anderen Initialisierungsaufgaben ausgeführt werden FinishedLaunching .
  2. Bildschirme – Unterklassen, die UIViewController jeden Bildschirm und sein Verhalten definieren. Bildschirme verbinden die Benutzeroberfläche mit Application Layer-Klassen und der allgemeinen API ( TaskItemManager ). In diesem Beispiel werden die Bildschirme im Code erstellt, aber sie könnten mit dem Schnittstellen-Generator von Xcode oder dem Storyboard-Designer entworfen worden sein.
  3. Bilder – Visuelle Elemente sind ein wichtiger Bestandteil jeder Anwendung. Tasky verfügt über Begrüßungsbildschirm- und Symbolbilder, die für iOS in normaler und Netzhautauflösung bereitgestellt werden müssen.

Startbildschirm

Der Startbildschirm ist ein MonoTouch.Dialog Bildschirm, der eine Liste der Aufgaben aus der SQLite-Datenbank anzeigt. Er erbt von DialogViewController code und implementiert ihn, um festzulegen, dass es eine Auflistung von TaskItem Objekten für die Root Anzeige enthält.

Er erbt von DialogViewController und implementiert Code, um den Stamm so festzulegen, dass er eine Sammlung von TaskItem-Objekten für die Anzeige enthält.

Die beiden wichtigsten Methoden im Zusammenhang mit der Anzeige und Interaktion mit der Aufgabenliste sind:

  1. PopulateTable – Verwendet die Business Layer-Methode TaskManager.GetTasks , um eine Sammlung von TaskItem Objekten abzurufen, die angezeigt werden sollen.
  2. Ausgewählt – Wenn eine Zeile berührt wird, wird die Aufgabe auf einem neuen Bildschirm angezeigt.

Bildschirm "Vorgangsdetails"

Vorgangsdetails ist ein Eingabebildschirm, über den Aufgaben bearbeitet oder gelöscht werden können.

Tasky verwendet MonoTouch.Dialogdie Spiegelungs-API, um den Bildschirm anzuzeigen, sodass keine UIViewController Implementierung vorhanden ist. Stattdessen instanziiert die HomeScreen Klasse und zeigt eine DialogViewController Using-Klasse TaskDialog aus der Application Layer an.

Dieser Screenshot zeigt einen leeren Bildschirm, der das Entry Attribut zum Festlegen des Wasserzeichentexts in den Feldern "Name " und "Notizen " veranschaulicht:

Dieser Screenshot zeigt einen leeren Bildschirm, der das Eintragsattribut zum Festlegen des Wasserzeichentexts in den Feldern

Die Funktionalität des Bildschirms "Vorgangsdetails " (z. B. Speichern oder Löschen einer Aufgabe) muss in der Klasse implementiert werden, da dies der Ort ist, an dem HomeScreen die MonoTouch.Dialog.BindingContext Aufgabe erstellt wird. Die folgenden HomeScreen Methoden unterstützen den Bildschirm "Vorgangsdetails":

  1. ShowTaskDetails – Erstellt einen MonoTouch.Dialog.BindingContext Zum Rendern eines Bildschirms. Er erstellt den Eingabebildschirm mithilfe der Spiegelung, um Eigenschaftsnamen und -typen aus der TaskDialog Klasse abzurufen. Zusätzliche Informationen, z. B. der Wasserzeichentext für die Eingabefelder, werden mit Attributen für die Eigenschaften implementiert.
  2. SaveTask – Auf diese Methode wird über ein OnTap Attribut in der TaskDialog Klasse verwiesen. Sie wird aufgerufen, wenn "Speichern " gedrückt wird, und verwendet einen MonoTouch.Dialog.BindingContext , um die vom Benutzer eingegebenen Daten abzurufen, bevor die Änderungen mithilfe TaskItemManager gespeichert werden.
  3. DeleteTask – Auf diese Methode wird über ein OnTap Attribut in der TaskDialog Klasse verwiesen. Die Daten werden TaskItemManager mithilfe des Primärschlüssels (ID-Eigenschaft) gelöscht.

Android-App

Das vollständige Xamarin.Android-Projekt ist unten dargestellt:

Android-Projekt ist hier dargestellt

Das Klassendiagramm mit nach Ebene gruppierten Klassen:

Das Klassendiagramm mit nach Ebene gruppierten Klassen

References

Das Android-App-Projekt muss auf die plattformspezifische Xamarin.Android-Assembly verweisen, um auf Klassen aus dem Android SDK zuzugreifen.

Sie muss auch auf das PCL-Projekt verweisen (z. B. TaskyPortableLibrary) für den Zugriff auf den allgemeinen Daten- und Geschäftsschichtcode.

TaskyPortableLibrary für den Zugriff auf den allgemeinen Daten- und Geschäftsschichtcode

Application Layer (AL)

Ähnlich wie bei der iOS-Version, die wir zuvor betrachtet haben, enthält die Anwendungsschicht in der Android-Version plattformspezifische Klassen, die zum Binden der Objekte erforderlich sind, die von der Core-Schnittstelle an die Benutzeroberfläche verfügbar gemacht werden.

TaskListAdapter – zum Anzeigen einer Liste<T> von Objekten müssen wir einen Adapter implementieren, um benutzerdefinierte Objekte in einem ListView. Der Adapter steuert, welches Layout für jedes Element in der Liste verwendet wird – in diesem Fall verwendet der Code ein integriertes Android-Layout SimpleListItemChecked.

Benutzeroberfläche (UI)

Die Benutzeroberfläche der Android-App ist eine Kombination aus Code und XML-Markup.

  • Ressourcen/Layout – Bildschirmlayouts und das Zeilenzellendesign als AXML-Dateien implementiert. Die AXML kann von Hand geschrieben oder visuell mithilfe des Xamarin UI-Designers für Android gestaltet werden.
  • Ressourcen/Drawable – Bilder (Symbole) und benutzerdefinierte Schaltfläche.
  • Bildschirme – Aktivitätsunterklassen, die jeden Bildschirm und sein Verhalten definieren. Verknüpft die Benutzeroberfläche mit Application Layer-Klassen und der allgemeinen API (TaskItemManager).

Startbildschirm

Der Startbildschirm besteht aus einer Aktivitätsunterklasse HomeScreen und der HomeScreen.axml Datei, die das Layout definiert (Position der Schaltfläche und Aufgabenliste). Der Bildschirm sieht wie folgt aus:

Der Bildschirm sieht wie folgt aus:

Der Code für den Startbildschirm definiert die Handler für das Klicken auf die Schaltfläche und das Klicken auf Elemente in der Liste sowie das Auffüllen der Liste in der OnResume Methode (sodass änderungen, die im Bildschirm "Aufgabendetails" vorgenommen wurden) angezeigt werden. Daten werden mit den Geschäftsebenen TaskItemManager und der TaskListAdapter aus der Anwendungsschicht geladen.

Bildschirm "Vorgangsdetails"

Der Bildschirm "Vorgangsdetails" besteht auch aus einer Activity Unterklasse und einer AXML-Layoutdatei. Das Layout bestimmt die Position der Eingabesteuerelemente, und die C#-Klasse definiert das Verhalten zum Laden und Speichern TaskItem von Objekten.

Die Klasse definiert das Verhalten zum Laden und Speichern von TaskItem-Objekten.

Alle Verweise auf die PCL-Bibliothek werden über die TaskItemManager Klasse ausgeführt.

Windows Phone-App

Das vollständige Windows Phone-Projekt:

Windows Phone-App Das vollständige Windows Phone-Projekt

Das folgende Diagramm zeigt die Klassen, die in Ebenen gruppiert sind:

In diesem Diagramm werden die Klassen dargestellt, die in Ebenen gruppiert sind.

References

Das plattformspezifische Projekt muss auf die erforderlichen plattformspezifischen Bibliotheken (z Microsoft.Phone . B. und System.Windows) verweisen, um eine gültige Windows Phone-Anwendung zu erstellen.

Außerdem muss auf das PCL-Projekt (z. B. TaskyPortableLibrary) verwiesen werden, um die TaskItem Klasse und Datenbank zu verwenden.

TaskyPortableLibrary zur Verwendung der TaskItem-Klasse und -Datenbank

Application Layer (AL)

Wie bei den iOS- und Android-Versionen besteht die Anwendungsebene aus den nicht visuellen Elementen, die dazu beitragen, Daten an die Benutzeroberfläche zu binden.

ViewModels

ViewModels umschließen Daten aus der PCL ( TaskItemManager) und stellt sie so dar, dass sie von silverlight-/XAML-Datenbindung genutzt werden kann. Dies ist ein Beispiel für plattformspezifisches Verhalten (wie im Dokument für plattformübergreifende Anwendungen erläutert).

Benutzeroberfläche (UI)

XAML verfügt über eine eindeutige Datenbindungsfunktion, die im Markup deklariert werden kann und die Zum Anzeigen von Objekten erforderliche Codemenge verringern kann:

  1. Seiten – XAML-Dateien und deren Codebehind definieren die Benutzeroberfläche und verweisen auf die ViewModels und das PCL-Projekt, um Daten anzuzeigen und zu sammeln.
  2. Bilder – Begrüßungsbildschirm, Hintergrund- und Symbolbilder sind ein wichtiger Bestandteil der Benutzeroberfläche.

MainPage

Die MainPage-Klasse verwendet die TaskListViewModel Daten zum Anzeigen von Daten mithilfe der Datenbindungsfeatures von XAML. Die Seite DataContext ist auf das Ansichtsmodell festgelegt, das asynchron aufgefüllt wird. Die {Binding} Syntax im XAML bestimmt, wie die Daten angezeigt werden.

TaskDetailsPage

Jede Aufgabe wird angezeigt, indem sie den TaskViewModel xaml-Code binden, der in der TaskDetailsPage.xaml definiert ist. Die Vorgangsdaten werden über die TaskItemManager In business Layer abgerufen.

Ergebnisse

Die resultierenden Anwendungen sehen auf jeder Plattform wie folgt aus:

iOS

Die Anwendung verwendet iOS-Standard-Benutzeroberflächendesign, z. B. die Schaltfläche "Hinzufügen", die in der Navigationsleiste positioniert wird, und das integrierte Plussymbol (+). Außerdem wird das Standardmäßige UINavigationController Verhalten der Schaltfläche "Zurück" verwendet und "Wisch-zu-Löschen" in der Tabelle unterstützt.

Außerdem wird das Standardmäßige Verhalten der UINavigationController-Schaltfläche Außerdem wird das Standardmäßige Verhalten der UINavigationController-Schaltfläche

Android

Die Android-App verwendet integrierte Steuerelemente, einschließlich des integrierten Layouts für Zeilen, für die ein "Teilstrich" angezeigt werden muss. Das Hardware-/Systemrückverhalten wird zusätzlich zu einer Schaltfläche "Zurück" auf dem Bildschirm unterstützt.

Das Hardware-/Systemrückverhalten wird zusätzlich zu einer Schaltfläche Das Hardware-/Systemrückverhalten wird zusätzlich zu einer Schaltfläche

Windows Phone

Die Windows Phone-App verwendet das Standardlayout, wobei die App-Leiste am unteren Bildschirmrand anstelle einer Navigationsleiste oben auffüllt wird.

Die Windows Phone-App verwendet das Standardlayout, wobei die App-Leiste am unteren Bildschirmrand anstelle einer Navigationsleiste oben auffüllt. Die Windows Phone-App verwendet das Standardlayout, wobei die App-Leiste am unteren Bildschirmrand anstelle einer Navigationsleiste oben auffüllt.

Zusammenfassung

Dieses Dokument enthält eine ausführliche Erläuterung, wie die Prinzipien des mehrschichtigen Anwendungsdesigns auf eine einfache Anwendung angewendet wurden, um die Wiederverwendung von Code auf drei mobilen Plattformen zu erleichtern: iOS, Android und Windows Phone.

Es hat den Prozess beschrieben, der zum Entwerfen der Anwendungsebenen verwendet wird, und erläutert, welche Code- und Funktionalität in jeder Ebene implementiert wurde.

Der Code kann von github heruntergeladen werden.