it-swarm.com.de

Android REST Client, Beispiel?

Auch wenn dieser Thread die Antwort akzeptiert hat, können Sie gerne andere Ideen vorschlagen, die Sie verwenden oder die Ihnen gefallen


Ich habe diese Artikel getroffen:

Und das führte mich zu diesem Google I/O 2010-Video über REST Clientanwendungen

Seitdem habe ich eine REST - Komponente als statische Komponente in meiner Application Controller-Klasse erstellt.

Ab jetzt sollte ich das Muster ändern. Jemand wies darauf hin, dass Google IOSched eine großartige Beispielanwendung für das Schreiben von REST Clients auf Android. Jemand anderes = sagte, dass dieser Weg zu kompliziert ist.

Kann uns jemand bitte zeigen, was die beste Vorgehensweise ist? Kurz und einfach.
Die IOSched-Anwendung ist für den Anwendungsfall eines Beispiels zu komplex.

111
Marek Sebera

EDIT 2 (Oktober 2017):

Es ist 2017. Verwenden Sie einfach Retrofit. Es gibt fast keinen Grund, etwas anderes zu benutzen.

BEARBEITEN:

Die ursprüngliche Antwort ist zum Zeitpunkt dieser Bearbeitung mehr als anderthalb Jahre alt. Obwohl die in der ursprünglichen Antwort vorgestellten Konzepte immer noch gültig sind, gibt es jetzt Bibliotheken, die Ihnen diese Aufgabe erleichtern. Noch wichtiger ist, dass einige dieser Bibliotheken Gerätekonfigurationsänderungen für Sie handhaben.

Die ursprüngliche Antwort wird unten als Referenz beibehalten. Nehmen Sie sich aber auch die Zeit, einige der Rest-Client-Bibliotheken auf Android zu untersuchen, um festzustellen, ob sie zu Ihren Anwendungsfällen passen. Das Folgende ist eine Liste einiger Bibliotheken, die ich ausgewertet habe. Es ist keineswegs beabsichtigt, eine vollständige Liste zu sein.


Ursprüngliche Antwort:

Vorstellung meines Ansatzes, REST Clients auf Android zu haben. Ich behaupte nicht, dass es das Beste ist :) Beachten Sie auch, dass ich dies als Antwort auf meine Anforderung gefunden habe. Möglicherweise müssen Sie mehr Ebenen haben/mehr Komplexität hinzufügen, wenn Ihr Anwendungsfall dies erfordert. Zum Beispiel habe ich überhaupt keinen lokalen Speicher; weil meine App den Verlust einiger REST Antworten tolerieren kann.

Mein Ansatz verwendet nur AsyncTasks unter der Decke. In meinem Fall "rufe" ich diese Tasks von meiner Activity -Instanz aus auf. Um jedoch Fälle wie die Bildschirmdrehung vollständig zu berücksichtigen, können Sie sie aus einem Service oder einem solchen aufrufen.

Ich habe meinen REST Client bewusst selbst als API ausgewählt. Dies bedeutet, dass die App, die meinen REST - Client verwendet, nicht einmal die tatsächlichen REST - URLs und das verwendete Datenformat kennen muss.

Der Client hätte 2 Ebenen:

  1. Obere Ebene: Der Zweck dieser Ebene besteht darin, Methoden bereitzustellen, die die Funktionalität der API REST widerspiegeln. Sie könnten beispielsweise eine Java - Methode für jede URL in Ihrer REST - API verwenden (oder sogar zwei - eine für GETs und eine für POSTs).
    Dies ist der Einstiegspunkt in die Client-API REST. Dies ist die Ebene, die die App normalerweise verwenden würde. Es könnte ein Singleton sein, aber nicht unbedingt.
    Die Antwort des REST - Aufrufs wird von dieser Ebene in ein POJO analysiert und an die App zurückgegeben.

  2. Dies ist die untergeordnete Ebene AsyncTask, die HTTP-Client-Methoden verwendet, um diesen REST -Aufruf tatsächlich auszuführen.

Außerdem habe ich mich für einen Rückrufmechanismus entschieden, um das Ergebnis der AsyncTasks an die App zurückzusenden.

Genug text Sehen wir uns jetzt einen Code an. Nehmen wir eine hypothetische REST API-URL - http://myhypotheticalapi.com/user/profile

Die oberste Ebene könnte folgendermaßen aussehen:

   /**
 * Entry point into the API.
 */
public class HypotheticalApi{   
    public static HypotheticalApi getInstance(){
        //Choose an appropriate creation strategy.
    }

    /**
     * Request a User Profile from the REST server.
     * @param userName The user name for which the profile is to be requested.
     * @param callback Callback to execute when the profile is available.
     */
    public void getUserProfile(String userName, final GetResponseCallback callback){
        String restUrl = Utils.constructRestUrlForProfile(userName);
        new GetTask(restUrl, new RestTaskCallback (){
            @Override
            public void onTaskComplete(String response){
                Profile profile = Utils.parseResponseAsProfile(response);
                callback.onDataReceived(profile);
            }
        }).execute();
    }

    /**
     * Submit a user profile to the server.
     * @param profile The profile to submit
     * @param callback The callback to execute when submission status is available.
     */
    public void postUserProfile(Profile profile, final PostCallback callback){
        String restUrl = Utils.constructRestUrlForProfile(profile);
        String requestBody = Utils.serializeProfileAsString(profile);
        new PostTask(restUrl, requestBody, new RestTaskCallback(){
            public void onTaskComplete(String response){
                callback.onPostSuccess();
            }
        }).execute();
    }
}


/**
 * Class definition for a callback to be invoked when the response data for the
 * GET call is available.
 */
public abstract class GetResponseCallback{

    /**
     * Called when the response data for the REST call is ready. <br/>
     * This method is guaranteed to execute on the UI thread.
     * 
     * @param profile The {@code Profile} that was received from the server.
     */
    abstract void onDataReceived(Profile profile);

    /*
     * Additional methods like onPreGet() or onFailure() can be added with default implementations.
     * This is why this has been made and abstract class rather than Interface.
     */
}

/**
 * 
 * Class definition for a callback to be invoked when the response for the data 
 * submission is available.
 * 
 */
public abstract class PostCallback{
    /**
     * Called when a POST success response is received. <br/>
     * This method is guaranteed to execute on the UI thread.
     */
    public abstract void onPostSuccess();

}

Beachten Sie, dass die App weder JSON noch XML (oder ein anderes Format) verwendet, die von der API REST direkt zurückgegeben werden. Stattdessen sieht die App nur die Bean Profile.

Dann könnte die untere Ebene (AsyncTask-Ebene) so aussehen:

/**
 * An AsyncTask implementation for performing GETs on the Hypothetical REST APIs.
 */
public class GetTask extends AsyncTask<String, String, String>{

    private String mRestUrl;
    private RestTaskCallback mCallback;

    /**
     * Creates a new instance of GetTask with the specified URL and callback.
     * 
     * @param restUrl The URL for the REST API.
     * @param callback The callback to be invoked when the HTTP request
     *            completes.
     * 
     */
    public GetTask(String restUrl, RestTaskCallback callback){
        this.mRestUrl = restUrl;
        this.mCallback = callback;
    }

    @Override
    protected String doInBackground(String... params) {
        String response = null;
        //Use HTTP Client APIs to make the call.
        //Return the HTTP Response body here.
        return response;
    }

    @Override
    protected void onPostExecute(String result) {
        mCallback.onTaskComplete(result);
        super.onPostExecute(result);
    }
}

    /**
     * An AsyncTask implementation for performing POSTs on the Hypothetical REST APIs.
     */
    public class PostTask extends AsyncTask<String, String, String>{
        private String mRestUrl;
        private RestTaskCallback mCallback;
        private String mRequestBody;

        /**
         * Creates a new instance of PostTask with the specified URL, callback, and
         * request body.
         * 
         * @param restUrl The URL for the REST API.
         * @param callback The callback to be invoked when the HTTP request
         *            completes.
         * @param requestBody The body of the POST request.
         * 
         */
        public PostTask(String restUrl, String requestBody, RestTaskCallback callback){
            this.mRestUrl = restUrl;
            this.mRequestBody = requestBody;
            this.mCallback = callback;
        }

        @Override
        protected String doInBackground(String... arg0) {
            //Use HTTP client API's to do the POST
            //Return response.
        }

        @Override
        protected void onPostExecute(String result) {
            mCallback.onTaskComplete(result);
            super.onPostExecute(result);
        }
    }

    /**
     * Class definition for a callback to be invoked when the HTTP request
     * representing the REST API Call completes.
     */
    public abstract class RestTaskCallback{
        /**
         * Called when the HTTP request completes.
         * 
         * @param result The result of the HTTP request.
         */
        public abstract void onTaskComplete(String result);
    }

So könnte eine App die API verwenden (in einem Activity oder Service):

HypotheticalApi myApi = HypotheticalApi.getInstance();
        myApi.getUserProfile("techie.curious", new GetResponseCallback() {

            @Override
            void onDataReceived(Profile profile) {
                //Use the profile to display it on screen, etc.
            }

        });

        Profile newProfile = new Profile();
        myApi.postUserProfile(newProfile, new PostCallback() {

            @Override
            public void onPostSuccess() {
                //Display Success
            }
        });

Ich hoffe, die Kommentare reichen aus, um das Design zu erklären. aber ich würde mich freuen mehr info zu geben.

95
curioustechizen

"Entwicklung von Android REST Client-Anwendungen" von Virgil Dobjanschi führte zu zahlreichen Diskussionen, da während der Sitzung kein Quellcode vorgestellt oder später bereitgestellt wurde.

Die einzige mir bekannte Referenzimplementierung (bitte kommentieren, wenn Sie mehr wissen) finden Sie unter Datadroid (die Google IO-Sitzung wird unter/presentation erwähnt). Es ist eine Bibliothek, die Sie in Ihrer eigenen Anwendung verwenden können.

Der zweite Link fragt nach dem "besten" REST Framework, das im Zusammenhang mit Stackoverflow ausführlich behandelt wird. Für mich ist die Anwendungsgröße wichtig, gefolgt von der Leistung der Implementierung.

  • Normalerweise verwende ich die einfache org.json-Implementierung, die seit API-Level 1 Teil von Android ist und daher die Anwendungsgröße nicht erhöht.
  • Für mich sehr interessant war die Information zu JSON-Parser-Performance in den Kommentaren: Ab Android 3.0 Honeycomb ist der GSON-Streaming-Parser als Android.util.JsonReader enthalten. Leider sind die Kommentare nicht mehr verfügbar.
  • Spring Android (das ich manchmal benutze) unterstützt Jackson und GSON. Die Spring Android RestTemplate Module-Dokumentation verweist auf eine Beispiel-App .

Daher halte ich mich bei komplexeren Szenarien an org.json oder GSON. Für die Architektur einer org.json-Implementierung verwende ich eine statische Klasse, die die Server-Anwendungsfälle darstellt (z. B. findPerson, getPerson). Ich rufe diese Funktionalität von einem Dienst auf und verwende Dienstprogrammklassen, die das Mapping (projektspezifisch) und das Netzwerk IO (meine eigene REST -Vorlage für einfaches GET oder POST) ausführen. Ich versuche, die Verwendung von Reflexion zu vermeiden.

11
ChrLipp

Verwenden Sie niemals AsynTask, um Netzwerkanforderungen auszuführen, oder was auch immer, das beibehalten werden muss. Async-Aufgaben sind stark an Ihre Aktivität gebunden. Wenn der Benutzer die Ausrichtung des Bildschirms seit der Neuerstellung der App ändert, wird die AsyncTask gestoppt.

Ich empfehle Ihnen, das Dienstmuster mit Intent Service und ResultReceiver zu verwenden. Schauen Sie sich RESTDroid an. Es ist eine Bibliothek, mit der Sie jede Art von REST asynchron ausführen und Ihre Benutzeroberfläche mit Request Listenern benachrichtigen können, die das Dienstmuster von Virgil Dobjanschi implementieren.

7

Es gibt eine weitere Bibliothek mit einer viel saubereren API und typsicheren Daten. https://github.com/kodart/Httpzoid

Hier ist ein einfaches Anwendungsbeispiel

Http http = HttpFactory.create(context);
http.post("http://example.com/users")
    .data(new User("John"))
    .execute();

Oder komplexer mit Rückrufen

Http http = HttpFactory.create(context);
http.post("http://example.com/users")
    .data(new User("John"))
    .handler(new ResponseHandler<Void>() {
        @Override
        public void success(Void ignore, HttpResponse response) {
        }

        @Override
        public void error(String message, HttpResponse response) {
        }

        @Override
        public void failure(NetworkError error) {
        }

        @Override
        public void complete() {
        }
    }).execute();

Es ist frisch neu, sieht aber sehr vielversprechend aus.

3
Arthur

Es gibt viele Bibliotheken und ich benutze diese: https://github.com/nerde/rest-resource . Dies wurde von mir erstellt, und wie Sie in der Dokumentation sehen können, ist es viel sauberer und einfacher als die anderen. Es ist nicht auf Android ausgerichtet, aber ich benutze es und es funktioniert ziemlich gut.

Es unterstützt HTTP Basic Auth. Es erledigt den Dirty-Job des Serialisierens und Deserialisierens von JSON-Objekten. Sie werden es mögen, besonders wenn Ihre API Rails like ist.

1
Diego

Haftungsausschluss: Ich bin an dem Open Source-Projekt rest2mobile beteiligt

Eine andere Alternative als REST Client ist rest2mobile .

Der Ansatz unterscheidet sich geringfügig, da er den Clientcode für den Dienst REST) mithilfe von concrete rest examples generiert. Der Code ersetzt den Dienst REST) = URL- und JSON-Payloads mit nativen Java -Methoden und POJOs. Außerdem werden Serververbindungen, asynchrone Aufrufe und POJO-Konvertierungen von/zu JSON automatisch verarbeitet.

Beachten Sie, dass dieses Tool in verschiedenen Versionen erhältlich ist (CLI, Plugins, Android/iOS/JS-Unterstützung). Sie können das Android Studio-Plugin verwenden, um die API direkt in Ihrer App zu generieren.

Alle Codes finden Sie auf Github hier .

1
Manu