แก้ไข 2 (ตุลาคม 2560):
มันคือปี 2017 เพียงแค่ใช้ Retrofit แทบไม่มีเหตุผลที่จะใช้อย่างอื่นเลย
แก้ไข:
คำตอบเดิมมีอายุมากกว่าหนึ่งปีครึ่งในขณะที่ทำการแก้ไขนี้ แม้ว่าแนวคิดที่นำเสนอในคำตอบเดิมยังคงมีอยู่ดังที่คำตอบอื่น ๆ ชี้ให้เห็น แต่ตอนนี้มีห้องสมุดที่ทำให้งานนี้ง่ายขึ้นสำหรับคุณ ที่สำคัญกว่านั้นไลบรารีเหล่านี้บางส่วนจะจัดการกับการเปลี่ยนแปลงการกำหนดค่าอุปกรณ์ให้คุณ
คำตอบเดิมจะถูกเก็บไว้ด้านล่างสำหรับการอ้างอิง แต่โปรดใช้เวลาตรวจสอบไลบรารีไคลเอ็นต์ Rest บางส่วนสำหรับ Android เพื่อดูว่าเหมาะสมกับกรณีการใช้งานของคุณหรือไม่ ต่อไปนี้เป็นรายชื่อไลบรารีบางส่วนที่ฉันได้ประเมินไว้ ไม่ได้มีวัตถุประสงค์เพื่อให้เป็นรายการที่ละเอียดถี่ถ้วน
คำตอบเดิม:
นำเสนอแนวทางของฉันในการมีไคลเอนต์ REST บน Android ฉันไม่ได้อ้างว่ามันดีที่สุด :) นอกจากนี้โปรดทราบว่านี่คือสิ่งที่ฉันคิดขึ้นเพื่อตอบสนองความต้องการของฉัน คุณอาจต้องมีเลเยอร์เพิ่มเติม / เพิ่มความซับซ้อนมากขึ้นหากกรณีการใช้งานของคุณต้องการ ตัวอย่างเช่นฉันไม่มีที่เก็บข้อมูลในตัวเครื่องเลย เนื่องจากแอปของฉันสามารถทนต่อการสูญเสียการตอบสนอง REST บางส่วนได้
แนวทางของฉันใช้เพียงแค่AsyncTask
อยู่ใต้ผ้าคลุม ในกรณีของฉันฉัน "เรียก" งานเหล่านี้จากActivity
อินสแตนซ์ของฉัน แต่หากต้องการพิจารณากรณีต่างๆเช่นการหมุนหน้าจออย่างครบถ้วนคุณอาจเลือกที่จะโทรหาพวกเขาจากสิ่งService
เหล่านี้
ฉันเลือกไคลเอนต์ REST ของฉันให้เป็น API อย่างมีสติ ซึ่งหมายความว่าแอปที่ใช้ไคลเอนต์ REST ของฉันไม่จำเป็นต้องตระหนักถึง REST URL จริงและรูปแบบข้อมูลที่ใช้
ลูกค้าจะมี 2 ชั้น:
เลเยอร์บนสุด: วัตถุประสงค์ของเลเยอร์นี้คือเพื่อให้เมธอดที่สะท้อนการทำงานของ REST API ตัวอย่างเช่นคุณสามารถมีหนึ่งวิธี Java ที่สอดคล้องกับทุก URL ใน REST API ของคุณ (หรือสองอย่างสำหรับ GET และอีกวิธีหนึ่งสำหรับ POSTs)
นี่คือจุดเข้าสู่ REST client API นี่คือเลเยอร์ที่แอปใช้ตามปกติ อาจเป็นซิงเกิลตัน แต่ไม่จำเป็น
การตอบสนองของการเรียก REST จะแยกวิเคราะห์โดยเลเยอร์นี้เป็น POJO และส่งกลับไปยังแอป
นี่คือAsyncTask
เลเยอร์ระดับล่างซึ่งใช้เมธอดไคลเอ็นต์ HTTP เพื่อออกไปข้างนอกและทำการเรียก REST นั้น
นอกจากนี้ฉันเลือกใช้กลไกการโทรกลับเพื่อสื่อสารผลลัพธ์ของAsyncTask
s กลับไปที่แอป
มีข้อความเพียงพอ มาดูโค้ดกันเลย ให้ใช้ URL REST API สมมุติ - http://myhypotheticalapi.com/user/profile
เลเยอร์บนสุดอาจมีลักษณะดังนี้:
/**
* 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();
}
โปรดทราบว่าแอปไม่ได้ใช้ JSON หรือ XML (หรือรูปแบบอื่นใด) ที่ส่งคืนโดย REST API โดยตรง Profile
แต่แอปเท่านั้นเห็นถั่ว
จากนั้นเลเยอร์ล่าง (เลเยอร์ AsyncTask) อาจมีลักษณะดังนี้:
/**
* 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);
}
นี่คือวิธีที่แอปอาจใช้ API (ในActivity
หรือ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
}
});
ฉันหวังว่าความคิดเห็นจะเพียงพอที่จะอธิบายการออกแบบ แต่เรายินดีที่จะให้ข้อมูลเพิ่มเติม