11. Mai 2022
Lesedauer 8 Min.
The Best of REST-API
Android und Retrofit
Mit der Bibliothek Retrofit können Sie einfach und schnell Daten über einen REST-basierten Webdienst Abrufen beziehungsweise Hochladen.

Die Dokumentation von Android erlaubt zwar einen einfachen Einstieg in die Entwicklung von Apps, verzichtet dabei aber auch ein wenig auf die Vorstellung von Open-Source Frameworks oder nützlicher Tools anderer Anbieter. Daher möchte dieser Workshop Ihnen die Retrofit Netzwerkbibliothek (Library) für Android vorstellen, die die Interaktion mit REST-basierten Webdiensten deutlich vereinfacht.REST-API (auch als RESTful API bekannt) steht für Representational State Transfer Application Programming Interface. Diese Schnittstelle ermöglicht den Austausch von Informationen, wenn diese sich auf unterschiedlichen Systemen befinden. Das heißt, dank einer REST-API ist es möglich, Informationen und Aufgaben auf verschiedene Server zu verteilen und mit Hilfe eines HTTP-Requests anzufordern.Hierbei steht REST für ein Softwarearchitektur-Paradigma und ermöglicht dann über die Programmierschnittstelle (API), die HTTP-Anfragen nutzt, auf Daten zuzugreifen. Wenn also eine Client-Anforderung über eine REST-API gestellt wird, überträgt diese eine Repräsentation des Ressourcenstatus an den Anforderer oder Endpunkt. Die Informationen werden in einem bekannten HTTP-Format wie JSON (JavaScript Object Notation), HTML, XLT, XML oder Plain Text bereitgestellt. Wobei zurzeit JSON das beliebteste Format darstellt.Der Prozess einer Client-Anfrage startet, wenn HTTP-Befehle verwendet werden, um Anfragen an einen Server zu senden. Die gängigsten HTTP-Befehle sind:Wenn der Client eine Ressource über die REST-API vom Server anfordert, sendet der nicht die Ressource zurück, sondern antwortet mit einer Darstellung der Ressource. REST-APIs zeichnen sich im Wesentlichen durch folgende Kriterien aus:Da es sich bei REST um Richtlinien aus einem Architektur-Muster handelt, kann es vom Entwickler flexibel implementiert werden. Durch diesen Vorteil ist es möglich, REST-APIs schneller und kompakter mit verbesserter Skalierbarkeit zu gestalten und so perfekt für die Entwicklung mobiler Apps zu nutzen.
REST-Client für Android, Java und Kotlin
Retrofit ist ein von Square als Open-Source entwickelter typsicherer REST-Client für Android, Java und Kotlin. Die Library bietet einfache Features für die Authentifizierung und Interaktion mit APIs und das Senden von Netzwerkanforderungen mit OKHTTP.Bei Retrofit werden URL und die Aufrufmethode wie GET, POST oder PUT innerhalb einer Annotation mitgegeben, hierdurch ist es dann auch möglich Variablen zu verwenden. Die Library macht das Herunterladen von JSON- oder XML-Daten von einer REST-API ziemlich einfach. Sobald die Daten heruntergeladen sind, erfolgt über ein Interface das Mapping von JSON auf ein Java-Objekt. Das heißt, sind die Daten heruntergeladen, werden sie in ein Plain Old Java Object (POJO) geparst. Retrofit modelliert den REST-Endpunkt direkt als Java-Schnittstelle, wodurch dieser dann sehr einfach zu verstehen und zu verwenden ist.Sie als Entwickler können Retrofit zur Durchführung der HTTP-Anfragen und Antworten schnell und effektiv verwenden. Hierbei bietet Retrofit noch folgende Vorteile:Von Nachteil kann es sein, dass Retrofit das Laden von Bildern nicht unterstützt und man daher eine andere Library wie Glide oder Picasso einsetzen muss. Außerdem ist das Setzen von Prioritäten nicht durchführbar.In diesem Workshop wird davon ausgegangen, dass Android Studio in der aktuellen Version zur Verfügung steht und installiert ist. Den Download und Hilfe zur Installation von Android Studio finden Sie unter https://developer.android.com/studio?hl=de. Retrofit benötigt mindestens das Android Support Library Package API 21 oder höher. Die Support-Bibliothek lässt sich aber auch mit dem Android SDK Manager unter dem Erweiterungssymbol im Start Dialogfenster nachinstallieren.Die zu erstellende Android-App soll in dem Beispiel dafür Sorge tragen, dass Sie eine einfache GET-Anfrage an eine REST-API mit Retrofit versenden. Hierfür benötigen Sie für die Verwendung von Retrofit nur eine Modellklasse, diese enthält die Objekte, die aus der JSON-Datei abgerufen werden sollen. Des Weiteren benötigen Sie die Retrofit-Instanz. Hierbei handelt es sich um eine Java-Klasse, um die Anfrage an eine REST-API zu senden und zu guter Letzt, die Schnittstellenklasse. Diese Java Klasse wird verwendet, um die Endpunkte zu definieren. Als erstes legen Sie aber für den Workshop ein neues Android Studio Projekt an.
Anlegender gewünschten Activity(Bild 1)
Basler
Wählen Sie hierfür im Startbildschirm einfach New Project. Daraufhin öffnet sich der Dialog New Project wie in Bild 1 gezeigt. Wählen Sie die Vorlage Empty Activity aus und klicken Sie auf Next.Jetzt legen Sie die grundlegenden Eigenschaften Ihres Projektes fest. Der Name wird später auf dem Device angezeigt. Wählen Sie hier einen prägnanten Namen für Ihre App. Im Beispiel verwenden wir den Begriff DemoRetrofitApp. Die Klassen und Dateien werden unter Android in Paketen (Packages) abgelegt. Seien Sie daher bei der Vergabe des Paketnamens besonders sorgfältig, vor allem, wenn Sie die App im Google Play Store veröffentlichen möchten. Hier muss der Paketname eindeutig sein.Schließen Sie das Dialogfenster über den Button Finish ab. Android Studio generiert jetzt automatisch eine Activity mit der im Bild 2 aufgezeigten Projektstruktur und öffnet die Klasse MainActivity.java.

MainActivity:So sieht die MainActivity in Android Studio aus(Bild 2)
Basler
Android-Apps werden immer zu einer baumartigen Struktur zusammengefasst. Hierbei bietet das Werkzeugfenster von Android Studio für den Entwickler mehrere Sichten an. Die Ansicht Project entspricht dem Aufbau der Ebenen innerhalb des Dateisystems, während die Sicht Android die Struktur eines Projektes abbildet. So erhalten Sie einen schnellen Zugriff auf die wichtigsten Dateien und Verzeichnisse.Für die Verwendung von Retrofit ist eine Berechtigung für den Zugriff auf das Internet in Ihrer App erforderlich. Ohne diese Einstellung wäre eine GET Anfrage per HTTP nicht möglich. Wie Sie sicher durch die Programmierung mit Android wissen, werden die Berechtigungen in der Manifest Datei der App eingetragen. Erweitern Sie daher die AndroidManifest.xml Datei um den folgenden Eintrag:
<uses-permission android:<span class="hljs-built_in">name</span>=
<span class="hljs-string">"android.permission.INTERNET"</span> />
Speichern Sie danach die Änderung in der XML-Datei ab.Bevor Sie im nächsten Schritt die Benutzeroberfläche für die Android-App erstellen, sollten Sie erst einmal Retrofit zu Ihrem Android Studio-Projekt hinzufügen. Hierfür erweitern Sie einfach die Datei build.gradle für das Modul App um die folgenden Abhängigkeiten (dependencies {...}) um einen Verweis auf den externen Code zu erhalten:
<span class="hljs-keyword">implementation</span> <span class="hljs-string">'com.squareup.retrofit2:retrofit:2.7.2'</span>
<span class="hljs-keyword">implementation</span>
<span class="hljs-string">'com.squareup.retrofit2:converter-gson:2.7.2'</span>
<span class="hljs-keyword">implementation</span> <span class="hljs-string">'com.squareup.okhttp3:okhttp:3.6.0'</span>
Alternativ können Sie auch über fileTree(...) die von Square zur Verfügung gestellte Retrofit Jar-Datei einbinden. Die erforderliche Retrofit Library können Sie als JAR-Datei unter https://square.github.io/retrofit/ herunterladen. Nachdem Download steht Ihnen die retrofit-2.9.x.jar-Datei mit allen notwenigen Klassendateien, Metadaten und Ressourcen für die Nutzung unter Android zur Verfügung. Das benötigte Buildskript würde dabei beispielhaft wie folgt aussehen:
<span class="hljs-keyword">dependencies</span> {
implementation <span class="hljs-keyword">fileTree</span>(dir: <span class="hljs-string">"libs"</span>,
<span class="hljs-keyword">include</span>:[<span class="hljs-string">"*.jar"</span>])
}
Mit den vorgenommenen Erweiterungen kann man jetzt Retrofit in seiner eigenen App verwenden. Die Angabe com.sq-convert legt fest, welches JSON-Format man verwenden möchte. Retrofit unterstützt neben GSON noch folgende JSON-Konverter:Im Beispiel wird der oben Aufgeführte Open Source GSON-Konverter für die Darstellung von JSON verwendet.In diesem Schritt wird das Layout für die App entworfen. Da es sich ja um eine einfache Demo-Anwendung handelt, wird nur eine ListView verwendet, um die Information der API anzuzeigen.Die Layout-Beschreibung kann auch vollständig in der Sprache XML modelliert werden. Die dafür angelegten Dateien werden im Unterverzeichnis res/layout abgelegt. Das folgende Beispiel activity_main.xml ist Bestandteil des Projektes und soll für die App abgeändert werden:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=<span class="hljs-string">"http://schemas.android.com/apk/res/android"</span>
<span class="hljs-string">xmlns:</span>tools=<span class="hljs-string">"http://schemas.android.com/tools"</span>
<span class="hljs-string">android:</span>layout_width=<span class="hljs-string">"match_parent"</span>
<span class="hljs-string">android:</span>layout_height=<span class="hljs-string">"match_parent"</span>
<span class="hljs-string">tools:</span>context=<span class="hljs-string">".MainActivity"</span>
<span class="hljs-string">android:</span>background=<span class="hljs-string">"@color/white"</span>>
<ListView
<span class="hljs-string">android:</span>id=<span class="hljs-string">"@+id/superListView"</span>
<span class="hljs-string">android:</span>layout_width=<span class="hljs-string">"wrap_content"</span>
<span class="hljs-string">android:</span>layout_height=<span class="hljs-string">"wrap_content"</span> <span class="hljs-regexp">/></span>
<span class="hljs-regexp"> </span>
<span class="hljs-regexp"></</span>LinearLayout>
Der Code im Beispielprogramm stellt das allgemeine Design der Activity dar. Das Listing zeigt den Aufbau als XML für die Struktur der Liste. Sie können das Layout auf Wunsch ganz einfach über die Auswahl Code im Android Studio-Designer anpassen. Bild 3 zeigt das geänderte Layout mit der einfachen ListView.

User Interfacemit dem Designer erstellen(Bild 3)
Basler
Unter Android besteht eine App aus mindestens einer Activity. Je nach Funktionsumfang können auch eine Vielzahl von Activities in einer App enthalten sein. In den meisten Fällen ist die Activity einer Bedienoberfläche aus Views oder ViewGroups zugeordnet. Activities stellen in Android die Grundbausteine einer App dar, die sich gegenseitig aufrufen können. Da wir in der Beispiel-App auch eine Modellklasse für die API benötigen, beginnen wir als erstes mit der Implementierung der Modellklasse.Erstellen Sie hierfür eine neue Java-Klasse. Öffnen Sie im Verzeichnis java/com.example.demoretrofitapp das Kontextmenü mit der rechten Maustaste und wählen Sie New/Java class. Vergeben Sie hier den Namen Results.java und übernehmen Sie den folgenden Code aus der Klasse:
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Results</span> </span>{
<span class="hljs-meta">@SerializedName(<span class="hljs-meta-string">"name"</span>)</span>
<span class="hljs-keyword">private</span> String demoName;
<span class="hljs-keyword">public</span> Results(String name) {
<span class="hljs-keyword">this</span>.demoName = name;
}
<span class="hljs-keyword">public</span> String getName() {
<span class="hljs-keyword">return</span> demoName;
}
}
Die Modellklasse Results.java enthält die Objekte aus dem JSON-Format. Im Beispiel besteht diese nur aus einem fiktiven Typ String mit der Bezeichnung name. Hiebet sollte die Annotation SerializedName immer den genauen Namen eines Objektes in der JSON-Datei anzeigen.
Die Retrofit-Instanz
Im nächsten Schritt wird die Retrofit-Instanz implementiert. Diese Java Klasse wird verwendet, um Anfragen per HTTP an eine API zu senden. Hierfür verwenden Sie die Klasse Retrofit.Builder aus der Retrofit-Library, der Sie nur die benötigte URL übergeben müssen, die die erforderlichen Daten enthält. Erstellen Sie also eine neue Java Klasse mit der Bezeichnung RetrofitClient.java und fügen Sie den folgenden Code hinzu:
public class RetrofitClient {
<span class="hljs-keyword"> private</span><span class="hljs-keyword"> static</span> RetrofitClient<span class="hljs-built_in"> instance </span>= null;
<span class="hljs-keyword"> private</span> Api demoApi;
<span class="hljs-keyword"> private</span> RetrofitClient() {
Retrofit retrofit =<span class="hljs-built_in"> new </span>Retrofit.Builder().baseUrl(Api.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
demoApi = retrofit.create(Api.class);
}
<span class="hljs-keyword"> public</span><span class="hljs-keyword"> static</span> synchronized RetrofitClient getInstance() {
<span class="hljs-built_in"> if </span>(instance == null) {
<span class="hljs-built_in"> instance </span>=<span class="hljs-built_in"> new </span>RetrofitClient();
}
<span class="hljs-built_in"> return </span>instance;
}
<span class="hljs-keyword"> public</span> Api getDemoApi() {
<span class="hljs-built_in"> return </span>demoApi;
}
}
Wie Sie im Code erkennen können, bietet Retrofit einen Builder zum Konstruieren des erforderlichen Objektes an. Der Builder benötigt hierzu einfach nur die Basis-URL, die für jeden Service-Aufruf verwendet wird. Des Weiteren wird eine entsprechende Converter Factory benötigt, die sich um das Parsen der gesendeten und empfangenden Daten kümmert. Im Beispiel wird die GsonConverterFactory benutzt, um die JSON-Daten der definierten Benutzerklasse, im Beispiel der demoApi, zuzuordnen.
Endpunkte
Haben Sie die Retrofit-Instanz implementiert, können Sie jetzt den API-Endpunkt festlegen. Einfach ausgedrückt ist ein API-Endpunkt der Eintrittspunkt in den Kommunikationskanal, wenn zwei Systeme interagieren. Der Endpunkt stellt somit das Mittel dar, über die API auf Ressourcen zuzugreifen, die sie vom Server benötigt.Im einfachsten Fall ist ein API-Endpunkt die URL eines Servers oder Dienstes. Retrofit definiert die Endpunkte innerhalb einer Schnittstellenklasse (Interface). Der Endpunkt bezieht sich hierbei auf den Pfad, über den die Informationen abgerufen werden. Erstellen Sie daher für das Beispiel eine neue Interface-Klasse mit der Bezeichnung Api. Das folgende Listing zeigt, wie die Implementierung aussehen sollte:
public <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Api</span> </span>{
<span class="hljs-built_in">String</span> BASE_URL = <span class="hljs-string">"https://webApiSample/demos/"</span>;
<span class="hljs-meta">@GET</span>(<span class="hljs-string">"info"</span>)
Call<<span class="hljs-built_in">List</span><results>> getInfoOf();
}
Der fiktive Endpunkt lautet im Beispiel ‚info', das Ziel besteht darin, Informationen von der API über eine GET-Anfrage zu erhalten. Zu diesem Zweck wird die entsprechende @Get-Annotaion verwendet.Im letzten Schritt wird jetzt über die Klasse MainActivity.java der API-Endpunkt aufgerufen, der in der Schnittstellenklasse Api definiert ist. Die Interface Api-Klasse sorgt dafür, dass die Informationen aus der API in der ListView angezeigt werden. Übernehmen Sie hierzu die Klasse MainActivity:
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AppCompatActivity</span> </span>{
ListView superListView;
<span class="hljs-meta">@Override</span>
protected <span class="hljs-keyword">void</span> onCreate(Bundle savedInstanceState) {
<span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
superListView = findViewById(R.id.superListView);
getInfoFromApi();
}
private <span class="hljs-keyword">void</span> getInfoFromApi() {
Call<<span class="hljs-built_in">List</span><Results>> call = RetrofitClient.getInstance().getDemoApi().getInfoFromApi();
call.enqueue(<span class="hljs-keyword">new</span> Callback<<span class="hljs-built_in">List</span><Results>>() {
<span class="hljs-meta">@Override</span>
public <span class="hljs-keyword">void</span> onResponse(Call<<span class="hljs-built_in">List</span><Results>> call, Response<<span class="hljs-built_in">List</span><Results>> response) {
<span class="hljs-built_in">List</span><Results> myDemoList = response.body();
<span class="hljs-built_in">String</span>[] oneInfos = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>[myDemoList.size()];
<span class="hljs-keyword">for</span> (<span class="hljs-built_in">int</span> i = <span class="hljs-number">0</span>; i < myDemoList.size(); i++) {
oneInfos[i] = myDemoList.<span class="hljs-keyword">get</span>(i).getName();
}
superListView.setAdapter(<span class="hljs-keyword">new</span> ArrayAdapter<<span class="hljs-built_in">String</span>>(getApplicationContext(), android.R.layout.simple_list_item_1, oneInfos));
}
<span class="hljs-meta">@Override</span>
public <span class="hljs-keyword">void</span> onFailure(Call<<span class="hljs-built_in">List</span><Results>> call, Throwable t) {
Toast.makeText(getApplicationContext(), <span class="hljs-string">"Es ist ein Fehler aufgetreten"</span>, Toast.LENGTH_LONG).show();
}
});
}
}
Die Initialisierung wird in der onCreate(...)-Methode in der Activity vorgenommen. Das Grundgerüst finden Sie in der Methode getInfoFromApi. Die Methode onFailure(...) zeigt eine Android Toast-Meldung, wenn die Information nicht erfolgreich in die ListView geladen wurden.
Fazit
Der Workshop sollte aufzeigen, wie einfach es inzwischen geworden ist, mit dem richtigen Framework schnell und effektive Lösungen in und für das Betreibssystem Android zu entwickeln. Die aufgezeigte Implementierung ist eine Standradimplementierung der Methode und lässt sich deshalb ohne großen Aufwand und mit wenig Zeitaufwand auf andere Apps oder Activities übertragen.Links zum Thema
<b>◼ <a href="https://square.github.io/retrofit/" rel="noopener" target="_blank">Retrofit von Square</a> <br/></b>