Android REST istemcisi, Örnek?


115

Bu ileti dizisi cevabı kabul etse bile, başka fikirler önermekten çekinmeyin, kullanın veya beğenin


Şu makalelerle tanıştım:

Bu da beni REST istemci uygulamaları hakkındaki bu Google I / O 2010 videosuna götürüyor

Şu andan beri, Uygulama denetleyicisi sınıfımda statik bileşen olarak REST bileşeni oluşturuyorum.

Şu andan itibaren, kalıbı değiştirmem gerektiğini düşünüyorum. Birisi Google IOSched uygulamasının Android'de REST istemcilerinin nasıl yazılacağına dair harika bir örnek olduğunu belirtti . Başka biri bu yolların çok karmaşık olduğunu söyledi.

Peki, herhangi biri bize en iyi uygulamanın ne olduğunu gösterebilir mi? Kısa ve basit bir şekilde.
IOSched uygulaması, örnek kullanım durumu için çok karmaşık.


Merhaba, Genelde "ws" adlı web servisi için ayrı paket geliştiriyorum, "WebServicUtils.java" adlı sınıfımı genelleştiriyorum. WebServiceUtils.java sınıfı, web hizmetine erişim yöntemlerine sahiptir. Tekniğimin en iyisi olup olmadığından emin değilim ama ws paketimi Android Uygulamasında her kopyaladığımda tekrar kullanılabilir, tekniğim hakkında daha fazla bilgi edinmek isterseniz bana bildirin.
Ketan Parmar

Youtube yorumcunun daha iyi bir alternatifi olduğunu düşünmüyorum. Çoğu zaman delicesine aşırı karmaşık ve ayrıntılı saçmalık olsalar bile, Android API'leri dahilinde çalışmalıyız.
Timmmm

Bir yan not olarak, Android için açık kaynaklı bir tutulma eklentisi olan Mechanoid, basit bir DSL kullanarak JSON-REST istemcileri oluşturabilir, bunun nasıl kullanılacağına dair bir kılavuz burada bulunabilir robotoworks.com/mechanoid-plugin/service-client-dsl (Bu eklentinin yazarıyım, utanmaz eklenti için özür dilerim!)
Ian Warwick

Bu, Android REST istemci uygulamasını öğrenen kişiler için çok yararlı olabilir. Dobjanschi'nin sunumu PDF'ye dönüştürüldü: drive.google.com/file/d/0B2dn_3573C3RdlVpU2JBWXdSb3c/…
Kay Zed

Yanıtlar:


99

EDIT 2 (Ekim 2017):

Yıl 2017. Sadece Retrofit kullanın. Başka bir şey kullanmak için neredeyse hiçbir neden yok.

DÜZENLE:

Orijinal yanıt, bu düzenleme sırasında bir buçuk yıldan fazladır. Orijinal yanıtta sunulan kavramlar hala geçerli olsa da, diğer yanıtların da işaret ettiği gibi, artık bu görevi sizin için kolaylaştıran kütüphaneler var. Daha da önemlisi, bu kitaplıklardan bazıları sizin için aygıt yapılandırma değişikliklerini ele alır.

Orijinal cevap referans için aşağıda saklanmıştır. Ancak, kullanım senaryolarınıza uyup uymadıklarını görmek için lütfen Android için Rest istemci kitaplıklarından bazılarını incelemeye zaman ayırın. Aşağıda değerlendirdiğim bazı kütüphanelerin bir listesi yer almaktadır. Hiçbir şekilde kapsamlı bir liste olması amaçlanmamıştır.


Orijinal Cevap:

Android'de REST istemcilere sahip olma yaklaşımımı sunuyorum. Yine de en iyisi olduğunu iddia etmiyorum :) Ayrıca, ihtiyacıma yanıt olarak bulduğum şeyin bu olduğunu unutmayın. Kullanım durumunuz gerektiriyorsa daha fazla katmana sahip olmanız / daha fazla karmaşıklık eklemeniz gerekebilir. Örneğin, yerel depolama alanım yok; çünkü uygulamam birkaç REST yanıtının kaybına tahammül edebiliyor.

Benim yaklaşımım sadece AsyncTaskkapakların altında s kullanıyor . Benim durumumda, bu Görevleri örneğimden "çağırıyorum" Activity; ancak ekran döndürme gibi durumları tam olarak hesaba katmak için onları a Serviceveya benzeri bir yerden aramayı seçebilirsiniz .

REST istemcimin kendisini bir API olarak bilinçli olarak seçtim. Bu, REST istemcimi kullanan uygulamanın gerçek REST URL'lerinden ve kullanılan veri biçiminden haberdar olmasına gerek olmadığı anlamına gelir.

Müşteri 2 katmana sahip olacaktır:

  1. Üst katman: Bu katmanın amacı, REST API'nin işlevselliğini yansıtan yöntemler sağlamaktır. Örneğin, REST API'nizdeki her URL'ye karşılık gelen bir Java yönteminiz olabilir (hatta iki - biri GET'ler ve biri POST'ler için).
    Bu, REST istemci API'sine giriş noktasıdır. Bu, uygulamanın normalde kullanacağı katmandır. Bir singleton olabilir, ancak zorunlu değildir.
    REST çağrısının yanıtı bu katman tarafından bir POJO olarak ayrıştırılır ve uygulamaya döndürülür.

  2. Bu, AsyncTaskgerçekten dışarı çıkmak ve bu REST çağrısını yapmak için HTTP istemci yöntemlerini kullanan alt düzey katmandır.

Ek olarak, s'lerin sonucunu AsyncTaskuygulamaya geri bildirmek için bir Geri Arama mekanizması kullanmayı seçtim .

Bu kadar metin yeter. Şimdi biraz kod görelim. Farazi bir REST API URL'si alalım - http://myhypotheticalapi.com/user/profile

En üst katman şu şekilde görünebilir:

   /**
 * 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();

}

Uygulamanın, doğrudan REST API tarafından döndürülen JSON veya XML'yi (veya başka bir biçimi) kullanmadığını unutmayın. Bunun yerine, uygulama yalnızca fasulyeyi görür Profile.

Ardından, alt katman (AsyncTask katmanı) şu şekilde görünebilir:

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

Bir uygulamanın API'yi ( Activityveya içinde Service) nasıl kullanabileceği aşağıda açıklanmıştır :

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

Umarım yorumların tasarımı açıklamak için yeterlidir; ama daha fazla bilgi vermekten memnuniyet duyarım.


Oldukça güzel kod örnekleri nedeniyle bu cevabı daha çok seviyorum. Teşekkürler
Marek Sebera

1
Muhtemelen hiçbir şeye değmez, bu gerçekten de Virgil Dobjanschi'nin tanımladığı gibi uygun bir RESTful MVC modelini takip etmiyor. Uygulamanın doğrudan kullandığı bir SQLite veritabanını kullanan tam bir ContentProvider katmanı eklemeniz gerekir. Aksi takdirde, bu Android için iyi, hafif bir REST istemcisidir.
Cooper

1
Küçük bir şey, şu Get / PostTask'larda execute çağırmanız gerekecek
Mo Kargas

1
Bu gerçekten harika. GetResponseCallback'i nasıl daha genel hale getirebilirim ki, böylece sadece bir Profil geri göndermez, yoksa API'den her veri türü için ayrı bir GetResponseCallback yapmayı önerir misiniz?

1
@MichaelHerbig Evet, GetResponseCallbackdaha genel yapmanın yolları var . Tercih ettiğim bir işaretleyici arayüz kullanmaktır : interface IGetResopnse{} Yanıt olabilecek tüm sınıfları belirtmek gibi . Sonra, ben class Profile implements IGetResponseNihayet, vb yapmak GetResponseCallbackile jenerik IGetResponseüst bağlı olarak : public abstract class GetResponseCallback<? extends IGetResponse>.
curioustechizen

11

Virgil Dobjanschi tarafından "Android REST istemci uygulamalarının geliştirilmesi", oturum sırasında hiçbir kaynak kodu sunulmadığı veya daha sonra sağlanmadığı için çok fazla tartışmaya yol açtı.

Bildiğim tek referans uygulaması (daha fazlasını biliyorsanız lütfen yorum yapın) adresinde mevcuttur Datadroid'de (Google IO oturumu / Presentation altında belirtilmiştir). Kendi uygulamanızda kullanabileceğiniz bir kitaplıktır.

İkinci bağlantı, yığın aşımı konusunda yoğun olarak tartışılan "en iyi" REST çerçevesini sorar. Benim için uygulama boyutu ve ardından uygulamanın performansı önemlidir.

  • Normalde, API düzey 1'den beri Android'in bir parçası olan ve bu nedenle uygulama boyutunu artırmayan düz org.json uygulamasını kullanıyorum.
  • JSON ayrıştırıcılarının performansıyla ilgili yorumlarda bulunan bilgiler benim için çok ilginçti : Android 3.0 Honeycomb'dan itibaren GSON'un akış ayrıştırıcısı android.util.JsonReader olarak dahil edilmiştir. Maalesef yorumlar artık mevcut değil.
  • Spring Android (bazen kullandığım) Jackson ve GSON'u destekliyor. Yay Android RestTemplate modül dosyaları bir işaret örnek uygulama .

Bu nedenle, daha karmaşık senaryolar için org.json veya GSON'a sadık kalıyorum. Bir org.json uygulamasının mimarisi için, sunucu kullanım durumlarını temsil eden statik bir sınıf kullanıyorum (ör. FindPerson, getPerson). Bu işlevi bir hizmetten çağırıyorum ve eşlemeyi (projeye özgü) ve ağ GÇ'sini (düz GET veya POST için kendi REST şablonum) yapan yardımcı sınıfları kullanıyorum. Yansıma kullanmaktan kaçınmaya çalışıyorum.


4
O'Reilly kitabı Programming Android, Dobjanschi'nin RESTful MVC modelinin tam bir uygulamasını içerir (bölüm 12-13).
Cooper

İpucu için teşekkürler: Amazon'da şu ifadeyi buldum: "Bölüm 12 ve 13 içerik sağlayıcılarla ilgileniyor. İçerik sağlayıcıların örnek kod ve örnek bir uygulamayla kapsamlı şekilde ele alınması, bu teknolojinin nasıl çalıştığı ve nasıl yapılabileceği konusunda bana birkaç yeni fikir verdi gerçek programlama durumlarında kullanılabilir. URI'leri kullanarak verileri depolamak ve bunlara başvurmak için içerik sağlayıcı çerçevesi, Android işletim sisteminin yeni özelliklerinden biridir. Teknolojiyi adım adım açıklamada harika bir iş çıkardınız! "
ChrLipp


Bu kodu ICS + üzerinde çalıştıran var mı? FinchVideo örneğinin altındaki todo dosyası kısa ve öz bir şekilde "- ICS altında çöküyor" ifadesini belirtir. Kod örneklerinin bozuk olduğunu keşfetmek için kitabı satın aldıktan sonra biraz hayal kırıklığına uğradım ...
eageranalyst

7

Ağ isteğini veya kalıcı olması gereken her şeyi gerçekleştirmek için AsynTask kullanmayın. Zaman uyumsuz Görev, etkinliğinize güçlü bir şekilde bağlıdır ve Uygulama yeniden oluşturulduğundan beri kullanıcı ekranın yönünü değiştirirse, AsyncTask durdurulur.

Intent Service ve ResultReceiver ile Hizmet kalıbını kullanmanızı öneririm. RESTDroid'e bir göz atın . Virgil Dobjanschi'nin hizmet modelini uygulayan İstek Dinleyicileri ile her türlü REST talebini eşzamansız olarak gerçekleştirmenize ve UI'nizi bilgilendirmenize olanak sağlayan bir kütüphanedir.


3

Daha temiz API ve tür açısından güvenli verilere sahip başka bir kitaplık var. https://github.com/kodart/Httpzoid

İşte basit bir kullanım örneği

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

Veya geri aramalarla daha karmaşık

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

Yeni, ama çok umut verici görünüyor.


AsyncTask üzerinde çalışıyor gibi görünüyor, uzun süre çalışan istekler ve aktiviteler arasında geçişler için iyi olmayan şey, çünkü Aktivite çıkıldığında AsyncTask sonlandırılacak.
Malachiasz

1

Dışarıda çok sayıda kitaplık var ve bunu kullanıyorum: https://github.com/nerde/rest-resource . Bu benim tarafımdan oluşturuldu ve belgelerde de görebileceğiniz gibi, diğerlerinden çok daha temiz ve basit. Android odaklı değil, ama içinde kullanıyorum ve oldukça iyi çalışıyor.

HTTP Temel Kimlik Doğrulamasını destekler. JSON nesnelerini serileştirme ve seriyi kaldırma gibi kirli işi yapar. Özellikle API'niz Rails gibi ise, beğeneceksiniz.


1

Sorumluluk reddi: rest2mobile açık kaynak projesine dahil oldum

REST istemcisi olarak başka bir alternatif de rest2mobile kullanmaktır .

Yaklaşım, somut dinlenme örnekleri kullandığı için biraz farklıdır. REST hizmeti için istemci kodunu oluşturmak üzere . Kod, REST URL'sini ve JSON yüklerini yerel java yöntemleri ve POJO'larla değiştirir. Ayrıca sunucu bağlantılarını, eşzamansız çağrıları ve POJO ile JSON dönüşümlerini otomatik olarak yönetir.

Bu aracın farklı şekillerde (cli, eklentiler, android / ios / js desteği) geldiğini ve API'yi doğrudan uygulamanızda oluşturmak için android stüdyo eklentisini kullanabileceğinizi unutmayın.

Tüm kodlar burada github'da bulunabilir .


3
Lütfen sitenizin reklamını yapmak yerine ilk bağlantıyı gerçek hedefle değiştirin.
Skydan

0

Android için hafif eşzamansız REST istemci kitaplığımızı açık kaynaklı hale getirdik, minimum gereksinimleriniz varsa ve çoklu iş parçacığını kendiniz ele almak istemiyorsanız yararlı bulabilirsiniz - temel iletişim için çok uygundur, ancak tam gelişmiş bir REST istemcisi değildir kütüphane.

Buna libRESTfulClient denir ve GitHub'da bulunabilir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.