YouTube Search App #2

Dieser Artikel ist ein Gastbeitrag von Tobias Oliver, Informatik-Student in Karlsruhe und begeisterter App-Entwickler. In diesem Artikel soll es um die XML-Verarbeitung (Atom) gehen. Allerdings an einem spannenden Beispiel, nicht dem alt-bekannten RSS-Reader. Wir holen uns einen Video-Feed von YouTube, stellen ihn hübsch dar und wollen am Ende natürlich das Video sehen.

Nachdem ich im letzten Artikel bereits den allgemeinen Umgang mit der YouTube Data API gezeigt habe, soll es nun mit der eigentlichen Entwicklung losgehen. Wir benötigen ein „YoutubeDataItem“, dass die Daten eines Videos enthält, sowie ein Modell, dass wiederrum die Items enthält und die Suche ausführt.

Um loszulegen, starten wir Visual Studio Express 2012 für Windows 8, wählen DateiNeues Projekt (bzw. File – New Project) und legen eine leere Visual C# App „YoutubeSearch“ an.

Für das Model brauchen wir eine neue Klasse. Also Rechtsklick auf den Projektnamen im Projektmappen-Explorer, Hinzufügen – Klasse… , den Namen „YoutubeDataModel.cs“ eingeben und hinzufügen.

Diese Datei werden wir für die beiden Klassen „YoutubeDataItem“ sowie „YoutubeDataModel“ verwenden. Visual Studio hat bereits eine Klasse YoutubeDataModel anhand des Namens der Datei erstellt. Diese setzen wir noch auf public um später noch darauf zuzugreifen und erstellen eine zweite Klasse „YoutubeDataItem

Das Item selbst ist nicht wahnsinnig kompliziert. Lediglich die Eigenschaften und die dazugehörigen getter/setter.

Der meiste darin ist selbsterklärend. Der getter von der Image-Eigenschaft liefert ein BitmapImage zurück, dass von einer URL geladen wird. Diese ist bei allen YouTube-Videos identisch, es ändert sich nur die jeweilige Video-ID. Die URL führt dann auf ein Vorschaubild des Videos und könnte z.B. so aussehen:

Der Subtitle ist für ein schöneres Design der Video-Kacheln. Es gibt dafür nur einen getter, da der Inhalt aus bereits bestehenden Inhalten (AuthorName und Duration) zusammengesetzt wird.

RelativeLikes und RelativeDislikes normen die Likes und Dislikes eines Videos auf 250. Damit lässt sich der Indikator für Likes/Dislikes später besser darstellen.

Nun zum Model und der Suchfunktion. Damit wir später möglichst wenig selbst managen müssen um die Daten darzustellen, bietet es sich an eine ObservableCollection<> als Speicher für die Items zu verwenden. Diese Collection wird dann „automatisch“ die Benutzeroberfläche informieren, wenn Sie sich verändert hat und die Sicht der Daten aktualisieren (siehe: INotifyPropertyChanged ).

Kommen wir nun zur Video-Suche. Dazu muss der Feed von der URL "http://gdata.youtube.com/feeds/api/videos?v=2&q=" + query  geparst werden. Damit die Suche den UI-Thread nicht blockiert, die App also weiterläuft und auf die Fertigstellung des „Such-Threads“ wartet, implementieren wir die Suche von vornherein asynchron. Mit C# 5.0 wurden dafür 2 neue Keywords eingeführt, async und await.

Für die Suche erstellen wir einen neue Methode. Diese nimmt den Suchanfrage-String entgegen und gibt ein true/false zurück, im Form eines Tasks, der asynchron ausgeführt wird. Dazu schreibt man wie gehabt public, dann das neue Keyword async, nun den Task und in spitzen Klammern den Rückgabetyp des Vorgangs, also bool.

Zusammen ergibt das alles public async Task<bool> SearchAsync(string query)

Der grobe Ablauf sieht etwa so aus:

  1. vorhandene Elemente in _items löschen
  2. URL mithilfe des Parameters query zusammenbasteln
  3. Http-Verbindung aufbauen und Feed runterladen
  4. XML-Verarbeitung starten
  5. nach „entry“-Knoten suchen
  6. bei jedem „entry“-Knoten ein neues YoutubeDataItem anlegen
  7. benötigte Eigenschaften filtern und zum Item hinzufügen
  8. Item zur ObservableCollection hinzufügen
  9. Anhand der Anzahl der Elemente prüfen, ob Suche erfolgreich war

Das schwierigste an diesen Schritten ist wahrscheinlich die Http-Verbindung und das richtige parsen. Dazu muss man die Struktur des Feeds kennen, was wir schon besprochen haben.

Nun übersetzen wir diesen Ablauf Schritt für Schritt in Quellcode.

1. _items.Clear();

2. Uri url = new Uri("http://gdata.youtube.com/feeds/api/videos?v=2&q=" + query);

3.

content enthält anschließend den gesamten Feed als string

4.

Der XmlReader kapselt die XML-Daten und stellt hilfreiche Methoden zur Verfügung zur einfachen Verarbeitung. Die while-Schleife durchläuft jeden Knoten innerhalb des root-Elements der XML-Datei (Feed). Das heißt, innerhalb der Schleife würden wir nur Zugriff auf die „entry“-Knoten haben (Zur Erinnering: „entry“ ist ein Video-Element). Um auf die Daten eines „entry“ zuzugreifen, müssen wir einen „Subtree“ erstellen und diesen durchlaufen. Dieser Subtree liefert dann die eigentlichen Informationen eines Videos. Wenn dieser Subtree erstellt wird, wird auch gleichzeitig ein neues Item erstellt. Die vorherige while-Schleife wird also gefüllt mit:

5. & 6.

7.

Warum wird mal mit await itemTree.ReadElementContentAsStringAsync() und mal mit itemTree["..."] auf die Daten zugegriffen? Weil die Daten innerhalb des Feeds unterschiedlich vorliegen. Wenn die Information selbst ein Element ist, dann nimmt man das erste (z.B: item.Title = await itemTree.ReadElementContentAsStringAsync()) , wenn die Information in einem Attribut steckt, dann das zweite unter Angabe des Attributnamens (z.B: itemTree["numLikes"]).

8. _items.Add(item);

9. return _items.Count != 0 ? true : false;
Tipp: Bedingten Ausdruck anstatt unnötige if/else-Konstrukte nutzen, wenn es sich anbietet.
z.B:
return _items.Count != 0 ? true : false;
statt

Wie das ganze vollständig aussieht, könnt ihr euch im Sourcecode ansehen, den es zum Download gibt.

Jetzt geht’s los mit der Anzeige! Um dem Windows 8 – Look-and-Feel gerecht zu werden, wollen wir die Videos natürlich in Kacheln anzeigen. Dazu nehmen wir das GridView und fügen es in unsere automatisch erstellte MainPage ein. Wir bauen uns die Oberfläche innerhalb in der „MainPage.xaml“ Datei und die Verknüpfung der Oberfläche mit unserem eben erstellten Modell wird dann in der Code-Behind-Datei „MainPage.xaml.cs“ erledigt.

Die MainPage kommt „ab Werk“ lediglich mit einem Grid. In das Grid fügen wir nun folgendes GridView ein:

<GridView Padding=“120,150,60,60″
VerticalAlignment=“Stretch“
HorizontalAlignment=“Stretch“
ItemTemplate=“{StaticResource Standard250x250ItemTemplate}“
ItemsSource=“{Binding Items}“>
</GridView>

Wir nutzen also vorerst ein GridView im Vollbild, dazu das vorgefertige „Standard250x250ItemTemplate“-Template für die Items und binden die ItemsSource (also die Quelle für die darzustellenden Items/Kacheln) an „Items“ (–> public ObservableCollection Items )

Damit alleine werden allerdings noch nichts sehen. Der DataContext muss noch konfiguriert und die Such-Methode gestartet werden. Wie gesagt, das machen wir im Code-Behind. Also öffnen wir MainPage.xaml.cs (Unterpunkt von MainPage.xaml).

Wir deklarieren innerhalb der MainPage-Klasse eine neue Variable, unser Model, mit: YoutubeDataModel model;.

In der bereits vorhandenen Methode OnNavigatedTo() erstellen wir nun unser Model, setzen es als DataContext der MainPage und starten probeweise eine Suchanfrage (hardcoded – also vorerst ohne Benutzereingabe). Da wir unsere Suche asynchron implementiert haben und auch starten werden, muss vorher die Methode OnNavigatedTo() um das Keyword async ergänzt werden:

Das await signalisiert dem Compiler nun, dass die nachfolgende Methode asynchron ausgeführt werden soll, sofern sie entsprechend implementiert wurde. Lässt man das await weg, wird eine Warnung ausgegeben und der Vorgang synchron im UI-Thread ausgeführt. Genauso gibt es eine Warnung, wenn eine Methode auf async gesetzt wird, jedoch den await-Operator nicht enthält.

Wenn ihr die App nun startet solltet ihr etwas ähnliches sehen:

YoutubeSearch-1

Nicht wahnsinnig hübsch, aber für den Anfang schon ganz gut. Beim nächsten Mal geht es dann ans Design. Also ItemTemplate, die Video-Seite, Suchfeld zum richtigen Suchen, und mehr.

Hier lässt sich das aktuelle Projekt bereits herunterladen:

  YouTube-Search #1 (24,1 KiB)

  1. TimeSpan String – Formatierung: http://msdn.microsoft.com/de-de/library/zdtaw1bw(v=vs.80).aspx
  2. INotifyPropertyChanged – Interface : http://msdn.microsoft.com/de-de/library/system.componentmodel.inotifypropertychanged.aspx
  3. Weitere Infos zu asynchroner Programmierung:  http://msdn.microsoft.com/de-de/library/vstudio/hh191443.aspx

Das könnte dich auch interessieren...

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.