แก้ไข 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 นั้น
นอกจากนี้ฉันเลือกใช้กลไกการโทรกลับเพื่อสื่อสารผลลัพธ์ของAsyncTasks กลับไปที่แอป
มีข้อความเพียงพอ มาดูโค้ดกันเลย ให้ใช้ 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
}
});
ฉันหวังว่าความคิดเห็นจะเพียงพอที่จะอธิบายการออกแบบ แต่เรายินดีที่จะให้ข้อมูลเพิ่มเติม