Klien Android REST, Contoh?

115

Sekalipun utas ini telah menerima jawaban, jangan ragu untuk mengusulkan ide lain, Anda gunakan atau suka


Saya telah menemukan artikel ini:

Dan itu membawa saya ke video Google I / O 2010 ini tentang aplikasi klien REST

Sejak sekarang, saya telah membuat komponen REST sebagai komponen statis di kelas pengontrol Aplikasi saya.

Mulai sekarang, saya pikir, saya harus mengubah polanya. Seseorang menunjukkan bahwa aplikasi Google IOSched adalah contoh yang bagus tentang cara menulis klien REST di Android. Orang lain mengatakan bahwa cara ini terlalu rumit.

Jadi, adakah yang bisa menunjukkan kepada kami praktik terbaik apa? Dengan cara yang singkat dan sederhana.
Aplikasi IOSched terlalu rumit untuk contoh kasus penggunaan.

Marek Sebera
sumber
Halo, Umumnya saya mengembangkan paket terpisah untuk layanan web bernama "ws", saya telah menggeneralisasi kelas bernama "WebServicUtils.java". Kelas WebServiceUtils.java memiliki metode untuk mengakses layanan web. Saya tidak yakin tentang teknik saya yang terbaik atau tidak tetapi dapat digunakan kembali setiap kali saya menyalin paket ws saya di Aplikasi Android, Beri tahu saya jika Anda ingin tahu lebih banyak tentang teknik saya.
Ketan Parmar
Saya rasa pemberi komentar youtube tidak memiliki alternatif yang lebih baik. Kami harus bekerja dalam API Android, meskipun API itu sering kali sangat rumit dan tidak masuk akal.
Timmmm
Sebagai catatan tambahan, Mechanoid, plugin gerhana open-source untuk Android dapat menghasilkan klien JSON-REST menggunakan DSL sederhana, panduan tentang cara menggunakannya dapat ditemukan di sini robotoworks.com/mechanoid-plugin/service-client-dsl (Saya adalah pembuat plugin ini, maaf untuk steker yang tidak tahu malu!)
Ian Warwick
Ini mungkin sangat membantu bagi orang-orang yang mempelajari implementasi klien Android REST. Presentasi Dobjanschi ditranskripsikan menjadi PDF: drive.google.com/file/d/0B2dn_3573C3RdlVpU2JBWXdSb3c/…
Kay Zed

Jawaban:

99

EDIT 2 (Oktober 2017):

Sekarang tahun 2017. Gunakan saja Retrofit. Hampir tidak ada alasan untuk menggunakan yang lain.

EDIT:

Jawaban aslinya sudah lebih dari satu setengah tahun pada saat pengeditan ini. Meskipun konsep yang disajikan dalam jawaban asli masih berlaku, seperti jawaban lain menunjukkan, sekarang ada perpustakaan di luar sana yang membuat tugas ini lebih mudah bagi Anda. Lebih penting lagi, beberapa pustaka ini menangani perubahan konfigurasi perangkat untuk Anda.

Jawaban asli disimpan di bawah untuk referensi. Tapi harap juga meluangkan waktu untuk memeriksa beberapa pustaka klien Rest untuk Android untuk melihat apakah mereka sesuai dengan kasus penggunaan Anda. Berikut ini adalah daftar dari beberapa perpustakaan yang telah saya evaluasi. Ini sama sekali tidak dimaksudkan sebagai daftar yang lengkap.


Jawaban Asli:

Mempresentasikan pendekatan saya untuk memiliki klien REST di Android. Saya tidak mengklaim ini adalah yang terbaik :) Juga, perhatikan bahwa ini adalah apa yang saya pikirkan sebagai tanggapan atas kebutuhan saya. Anda mungkin perlu memiliki lebih banyak lapisan / menambahkan lebih banyak kerumitan jika kasus penggunaan Anda menuntutnya. Misalnya, saya tidak memiliki penyimpanan lokal sama sekali; karena aplikasi saya dapat mentolerir hilangnya beberapa respons REST.

Pendekatan saya menggunakan just AsyncTasks under the covers. Dalam kasus saya, saya "memanggil" Tugas ini dari Activityinstance saya ; tetapi untuk sepenuhnya memperhitungkan kasus-kasus seperti rotasi layar, Anda dapat memilih untuk memanggilnya dari salah satu Serviceatau semacamnya.

Saya secara sadar memilih klien REST saya sendiri untuk menjadi API. Artinya, aplikasi yang menggunakan klien REST saya bahkan tidak perlu mengetahui URL REST aktual dan format data yang digunakan.

Klien akan memiliki 2 lapisan:

  1. Lapisan atas: Tujuan dari lapisan ini adalah untuk menyediakan metode yang mencerminkan fungsionalitas REST API. Misalnya, Anda dapat memiliki satu metode Java yang sesuai dengan setiap URL di REST API Anda (atau bahkan dua - satu untuk GET dan satu untuk POST).
    Ini adalah titik masuk ke API klien REST. Ini adalah lapisan yang biasanya digunakan aplikasi. Bisa jadi tunggal, tapi belum tentu.
    Respons panggilan REST diurai oleh lapisan ini menjadi POJO dan dikembalikan ke aplikasi.

  2. Ini adalah AsyncTasklapisan tingkat bawah, yang menggunakan metode klien HTTP untuk benar-benar keluar dan melakukan panggilan REST itu.

Selain itu, saya memilih untuk menggunakan mekanisme Callback untuk mengkomunikasikan hasil dari AsyncTaskkembali ke aplikasi.

Cukup teks. Mari kita lihat beberapa kode sekarang. Mari kita ambil URL REST API hipotetis - http://myhypotheticalapi.com/user/profile

Lapisan atas mungkin terlihat seperti ini:

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

}

Perhatikan bahwa aplikasi tidak menggunakan JSON atau XML (atau format lain apa pun) yang dikembalikan oleh REST API secara langsung. Sebaliknya, aplikasi hanya melihat kacang Profile.

Kemudian, lapisan bawah (lapisan AsyncTask) mungkin terlihat seperti ini:

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

Berikut ini cara aplikasi menggunakan API (dalam Activityatau 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
            }
        });

Saya harap komentarnya cukup untuk menjelaskan desainnya; tapi dengan senang hati saya akan memberikan info lebih lanjut.

curioustechizen
sumber
Saya suka jawaban ini lebih karena contoh kode yang cukup bagus. Terima kasih
Marek Sebera
1
Mungkin tidak ada nilainya, ini tidak benar-benar mengikuti pola MVC RESTful yang tepat, seperti yang dijelaskan oleh Virgil Dobjanschi. Anda perlu menggabungkan lapisan ContentProvider penuh, yang menggunakan database SQLite yang langsung digunakan aplikasi. Jika tidak, ini adalah klien REST yang bagus dan ringan untuk Android.
Cooper
1
Satu hal kecil, Anda harus memanggil eksekusi pada Get / PostTask itu
Mo Kargas
1
Ini sangat bagus. Bagaimana saya membuat GetResponseCallback lebih umum, sehingga tidak hanya meneruskan Profil kembali, atau apakah Anda menyarankan untuk membuat GetResponseCallback terpisah untuk setiap jenis data dari API?
1
@MichaelHerbig Ya, ada cara untuk membuatnya GetResponseCallbacklebih umum. Yang saya lebih suka adalah menggunakan antarmuka penanda : Suka interface IGetResopnse{} menunjukkan semua kelas yang bisa menjadi tanggapan. Lalu, saya punya class Profile implements IGetResponsedll Akhirnya, membuat GetResponseCallbackgenerik dengan IGetResponsesebagai batas atas : public abstract class GetResponseCallback<? extends IGetResponse>.
curioustechizen
11

"Mengembangkan aplikasi klien Android REST" oleh Virgil Dobjanschi menyebabkan banyak diskusi, karena tidak ada kode sumber yang disajikan selama sesi atau diberikan setelahnya.

Satu-satunya implementasi referensi yang saya tahu (beri komentar jika Anda tahu lebih banyak) tersedia di Datadroid (sesi Google IO disebutkan di bawah / presentasi). Ini adalah perpustakaan yang dapat Anda gunakan dalam aplikasi Anda sendiri.

Tautan kedua meminta kerangka kerja REST "terbaik", yang banyak dibahas di stackoverflow. Bagi saya ukuran aplikasi itu penting, diikuti oleh kinerja implementasinya.

  • Biasanya saya menggunakan implemantasi org.json biasa, yang merupakan bagian dari Android sejak API level 1 dan karena itu tidak meningkatkan ukuran aplikasi.
  • Bagi saya yang sangat menarik adalah informasi yang ditemukan tentang kinerja parser JSON di komentar: mulai Android 3.0 Honeycomb, parser streaming GSON disertakan sebagai android.util.JsonReader. Sayangnya, komentar tersebut sudah tidak tersedia lagi.
  • Spring Android (yang terkadang saya gunakan) mendukung Jackson dan GSON. The Semi Android RestTemplate Modul dokumentasi poin ke aplikasi sampel .

Oleh karena itu saya tetap berpegang pada org.json atau GSON untuk skenario yang lebih kompleks. Untuk arsitektur implementasi org.json, saya menggunakan kelas statis yang mewakili kasus penggunaan server (misalnya findPerson, getPerson). Saya menyebut fungsi ini dari layanan dan menggunakan kelas utilitas yang melakukan pemetaan (khusus proyek) dan jaringan IO (template REST saya sendiri untuk GET atau POST biasa). Saya mencoba menghindari penggunaan refleksi.

ChrLipp
sumber
4
Buku O'Reilly, Programming Android, menampilkan implementasi penuh pola RESTful MVC Dobjanschi (bab 12-13).
Cooper
Terima kasih atas petunjuknya: Saya menemukan pernyataan ini di Amazon: "Bab 12 dan 13 berurusan dengan penyedia konten. Perlakuan ekstensif terhadap penyedia konten dengan kode contoh dan aplikasi sampel memberi saya beberapa wawasan baru tentang cara kerja teknologi ini, dan cara kerjanya digunakan dalam situasi pemrograman nyata. Kerangka penyedia konten untuk menyimpan dan mereferensikan data menggunakan URI adalah salah satu fitur baru dari sistem operasi Android. Kerja bagus dalam menjelaskan teknologi langkah demi langkah! "
ChrLipp
2
Kode ada di github.com/bmeike/ProgrammingAndroid2Examples (tapi bab hilang, Anda dapat menemukannya di kode edisi pertama github.com/bmeike/ProgrammingAndroidExamples )
ChrLipp
Adakah yang bisa mendapatkan kode ini berjalan di ICS +? File rencana di bawah contoh FinchVideo secara ringkas menyatakan "- Mogok di bawah ICS". Saya agak kecewa setelah membeli buku untuk menemukan contoh kode rusak ...
eageranalyst
7

Jangan pernah menggunakan AsynTask untuk melakukan permintaan jaringan atau apa pun yang perlu dipertahankan. Tugas Asinkron sangat terikat dengan aktivitas Anda dan jika pengguna mengubah orientasi layar sejak Aplikasi dibuat, AsyncTask akan dihentikan.

Saya menyarankan Anda untuk menggunakan pola Layanan dengan Intent Service dan ResultReceiver. Lihatlah ke RESTDroid . Ini adalah pustaka yang memungkinkan Anda melakukan segala jenis permintaan REST secara asinkron dan memberi tahu UI Anda dengan Request Listeners yang mengimplementasikan pola layanan Virgil Dobjanschi.

Pierre Criulanscy
sumber
3

Ada pustaka lain dengan API yang jauh lebih bersih dan data yang aman untuk tipe. https://github.com/kodart/Httpzoid

Berikut ini contoh penggunaan sederhana

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

Atau lebih kompleks dengan callback

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

Ini segar baru, tapi terlihat sangat menjanjikan.

Arthur
sumber
Sepertinya berjalan di AsyncTask, yang tidak baik untuk permintaan yang berjalan lama dan beralih antar aktivitas, karena AsyncTask akan dimatikan saat Aktivitas keluar.
Malachiasz
1

Ada banyak perpustakaan di luar sana dan saya menggunakan yang ini: https://github.com/nerde/rest-resource . Ini dibuat oleh saya, dan, seperti yang Anda lihat di dokumentasi, jauh lebih bersih dan sederhana daripada yang lain. Ini tidak fokus pada Android, tapi saya menggunakannya dan bekerja dengan cukup baik.

Ini mendukung HTTP Basic Auth. Itu melakukan pekerjaan kotor serialisasi dan deserialisasi objek JSON. Anda akan menyukainya, terutama jika API Anda seperti Rails.

Diego
sumber
1

Penafian: Saya terlibat dalam proyek open source rest2mobile

Alternatif lain sebagai klien REST adalah menggunakan rest2mobile .

Pendekatannya sedikit berbeda karena menggunakan contoh lain yang konkret untuk menghasilkan kode klien untuk layanan REST. Kode tersebut menggantikan URL REST dan payload JSON dengan metode java asli dan POJO. Ini juga secara otomatis menangani koneksi server, pemanggilan asinkron dan POJO ke / dari konversi JSON.

Perhatikan bahwa alat ini hadir dalam berbagai rasa (cli, plugin, dukungan android / ios / js) dan Anda dapat menggunakan plugin studio android untuk membuat API langsung ke aplikasi Anda.

Semua kode dapat ditemukan di github di sini .

Manu
sumber
3
Harap ganti tautan pertama dengan target sebenarnya alih-alih mengiklankan situs Anda.
Skydan
0

Kami memiliki sumber terbuka pustaka klien REST asinkron ringan kami untuk Android, Anda mungkin merasa berguna jika Anda memiliki persyaratan minimal dan tidak ingin menangani multithreading sendiri - sangat OK untuk komunikasi dasar tetapi bukan klien REST yang lengkap Perpustakaan.

Ini disebut libRESTfulClient dan dapat ditemukan di GitHub .

bk138
sumber