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 AsyncTask
s under the covers. Dalam kasus saya, saya "memanggil" Tugas ini dari Activity
instance saya ; tetapi untuk sepenuhnya memperhitungkan kasus-kasus seperti rotasi layar, Anda dapat memilih untuk memanggilnya dari salah satu Service
atau 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:
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.
Ini adalah AsyncTask
lapisan 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 AsyncTask
kembali 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 Activity
atau 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.