#rTsd – Road to Surface Duo, das Entwicklertagebuch: Teil 4
Bisher erschienene Artikel zur Serie:
- #rTsd – Road to Surface Duo, das Entwicklertagebuch: Teil 1 (Idee, Motivation und Gestaltung)
- #rTsd – Road to Surface Duo, das Entwicklertagebuch: Teil 2 (Erste Schritte in C# und XAML)
- #rTsd – Road to Surface Duo, das Entwicklertagebuch: Teil 3 (Fragen und Antworten)
- #rTsd – (aktuell) Road to Surface Duo, das Entwicklertagebuch: Teil 4 (Service und Navigation)
tl;dr: Neue Features in Kürze erklärt
Für alle in Eile hier ein Abriss der neuen Features der #rTsd-App in Kürze. Manche von diesen sind im folgenden Beitrag ausführlicher erklärt. Den aktuellen Quelltext hierzu findet ihr wie immer auf GitHub.
Drawer hinzugefügt: Mit einem Tap auf das Dr. Windows Logo fährt nun ein Drawer (Flyout-Menu) heraus. Dieses bietet App-interne Informationen und einen Punkt zur Navigation zur „AboutPage“.
AboutPage aufbereitet: Die AboutPage, also die Informationsseite der App, enthält nun besser gestalteten Text als auch Buttons zum GitHub Repository der App und Dr. Windows an sich.
Services hinzugefügt: Durch Dependency Injection ist nun ein MockedFeedService als auch ein FeedService mit realen Daten in der App verfügbar.
Navigation hinzugefügt: Es ist nun möglich, zur Detailansicht zu navigieren. Zur besseren Darstellung wurde ein eigener „selected style“ für Listenelemente implementiert
Detailseite hinzugefügt: Es werden nun Detailinformationen der Seite als aufbereiteter HTML-Text in einer eigenen Ansicht dargestellt. Zusätzlich enthält diese Page Buttons zum Teilen und Aufrufen der Artikel direkt auf drwindows.de.
XAML wurde vereinfacht: Durch neue Learnings war ich in der Lage, die Komplexität mancher XAML-Pages stark zu vereinfachen. Es gibt nun kein verwirrendes RelativeLayout mehr und wiederkehrende Elemente wurden in eigene Controls ausgelagert.
Service, bitte
Nachdem wir uns in den letzten Beiträgen um die Grundpfeiler der Oberfläche gekümmert haben, sorgen wir nun dafür, dass wir auch die ersten Schritte in Richtung der Datenbeschaffung mittels eines Service gehen.
Ein Service (Docs, Wiki) bei Xamarin kommt meist Hand in Hand mit einem weiteren spannenden Bestandteil des Ökosystems, der so genannten Dependency Injection (Docs, Wiki).
Diese beiden Entwicklungspattern und -paradigmen in Gänze zu erklären, würde den Rahmen dieser kleinen Artikelserie sprengen. Deswegen beschränke ich mich auf eine abstrakte und vereinfache Darstellung der Dinge.
Dependency Injection ist Bestandteil einer nach dem Single-Responsibility-Prinzip ausgelegten Softwarearchitektur. Im Grunde bedeutet dies für uns, dass alle global in der App verfügbaren Singeltons, wie beispielsweise Services, an einem Ort verwaltet werden. Dies ist bei uns die App.xaml.cs Datei.
Service, zu Deutsch „Dienst“, ist eine in sich geschlossene Einheit, die sich um ein dediziertes Themengebiet kümmert und dessen Komplexität nach außen hin abschottet. Im Falle der #rTsd-App ist dies der FeedService.cs. Dieser kümmert sich um das Abrufen und Parsen des Dr. Windows Feeds. Das dazugehörige Pattern ist unter dem Namen „Serviceorientierte Architektur“ bekannt.
Kurzer Exkurs für Service Interessierte:
Für kommende Entwicklungsphasen benötigen wir neben dem Service für die realen Daten noch einen weiteren, welcher uns stets die gleichen und somit testbaren Resultate liefert. Dies ist in der App der MockedFeedService.cs.
Damit für die App, welche an sich nicht wissen darf ,welchen genauen Service sie bekommt, alles gleich aussieht, gibt es das generische Interface IElementService.cs. Diese Schnittstelle wird von beiden Services implementiert und beschreibt den zwingend erforderlichen Methodenumfang. In diesem Beispiel ist dies die Methode GetAllAsync(bool forceReload = false) welche alle verfügbaren Items zurück gibt.
Um nun dynamisch den realen oder den gemocked‘ten Service zu verwenden, ist es beispielsweise möglich, in der App.xaml.cs mit Compiler Flags arbeiten. Diese Flags können unter anderem die aktuell eingestellte Run Konfiguration von Visual Studio sein.
Der folgende Ausschnitt zeigt, wie im Fallse eines DEBUG-Builds der gemockedte Service und in allen anderen Fällen der für die realen Daten verwendetet wird.
Im GitHub Repository ist diese Funktionalität der Einfacheit halber erst einmal deaktiviert. Hier wird immer der FeedService.cs verwendet, welcher reale Daten vom Dr. Windows Server lädt.
Navigation
Damit die App nun mehr als nur die Liste aller Beiträge anzeigen kann, wird eine weitere Page (Ansicht) benötigt. Diese soll detaillierte Informationen zum ausgewählten Beitrag anzeigen.
Hierzu müssen zwei Dinge implementiert werden. Einerseits die gewünschte Detailansicht, andererseits eine Methodik, um diese auch aufrufen zu können
Mit Einführung der Shell in Xamarin.Forms wurde auch eine weitere Möglichkeit der Navigation innerhalb einer App eingeführt. Diese erinnert mich sehr stark an ASP-NET Core URL-basierten Routen. Mehr Informationen hierzu findet ihr in den entsprechenden Docs Seiten.
Da für mich persönlich dieses neue Feature eine unnötige zusätzliche Schicht an Komplexität und Quellcode für unsere kleine App bedeutet, entschied ich mich dagegen, diese neue Methodik zu verwenden.
Stattdessen kommt der mehr traditionelle Ansatz der hierarchischen Navigation zum Einsatz. Hierbei wird beim Tap auf ein Listenelement ein Command-Binding mit dazugehörigem Parameter, welcher der selektierte Beitrag ist, im ItemsViewModel.cs abgefeuert. Dieses wiederum baut eine ItemDetailPage.cs mit entsprechenden ViewModel auf, zeigt diese an, und setzt die gemachte Selektion des Listenelements in der Oberfläche zurück.
Durch den Einsatz von in Xamarin integrierten Navigationsfähigkeiten funktioniert auch der in Android vorhandene „Hardware“-Zurück-Button gleich mit.
Bis ins kleinste Detail
Eine Navigation bringt nichts ohne ein Ziel. In diesem Falle ist dies die viel beschriebene Detailansicht.
Diese besteht aus dem von den Listenelementen bekannten großen „Hero“-Bildern der Artikel und dem Titel. Diese Komponente können wir dank einen in dieser Phase der App eingeführten ControlTemplate (Docs, Quelltextdatei) eins zu eins wiederverwenden und sparen uns hiermit fehleranfällige Kopierarbeit.
Spannender ist die Anzeige des eigentlichen Beitragsinhaltes. Dieser ist innerhalb der Datenstruktur ein durch html-Tags formatierter Text angebildet.
Damit dieser in der App nicht wie ein Fremdkörper aussieht wird der Text im ViewModel der Page (ItemsDetailViewModel.cs) noch aufbereitet bevor er angezeigt wird.
Dabei wird dem html-Text die in der Applikation hinterlegte container.html–Datei vorgeschaltet. Diese beinhaltet rudimentäre Einstellungen und Darstellungsattribute für den rohen html-Inhalt des Posts. Mir ist bewusst, dass hierdurch keine valide html-Struktur entsteht, jedoch langt es für dieses Szenario aus. Denn es funktioniert wie es soll.
Da der später angezeigte und nun gestylte html-Text noch das Artikelbild in sich selbst enthält, wir es aber in unsere eigenen Komponente ebenfalls anzeigen, muss dieses aus dem Inhalt verschwinden. Dies passiert mit einer recht groben Regular Expression (Wiki, Docs) in Zeile 18 des Quelltextauschnittes.
Somit steht nun der Darstellung der Detailansicht nichts im Wege. Um den Dr. Windows Beitrag noch teilbar und im Web aufrufbar zu gestalten, enthält die Page noch zwei Buttons, welche mit einfachen Kommandos diese Funktionalität im ViewModel triggern.
Wie geht es weiter?
Im Grunde ist nun unsere kleine #rTsd-App fertig. Alle Features für das MVP (MinimumViable Product) sind implementiert. Nun warten wir einmal mehr auf Microsoft und hoffen auf neue Entwicklungsdetails zum Surface Duo. Anfang 2020 soll es für Entwickler hier neue Informationen geben. Wir können also gespannt sein.
Ansonsten stehen natürlich noch weitere, kleinere Verbesserungen an. So will ich das Threading im Hintergrund zum Datenladen besser verstehen als auch oft XAML-Einstellungen in zentrale Style-Einträge umbauen.
Themen:
- Entwicklung
- News
Über den Autor
Tobias Scholze
Bayrischer Open Source- und Community-Enthusiast, Verfechter des neuen Microsoft und Wandler zwischen den Betriebssystemwelten. #communityrocks Von Herzen ein Nerd mit der festen Überzeugung, dass man gemeinsam und durch den Einsatz von moderner IT die Welt für jeden ein Stückchen besser machen kann.