Ứng dụng khách Android REST, Mẫu?


115

Ngay cả khi chủ đề này đã được chấp nhận câu trả lời, hãy thoải mái đề xuất các ý tưởng khác, bạn sử dụng hoặc thích


Tôi đã gặp những bài báo này:

Và điều đó dẫn tôi đến video Google I / O 2010 này về các ứng dụng khách REST

Kể từ bây giờ, tôi đã tạo thành phần REST dưới dạng thành phần tĩnh trong lớp Bộ điều khiển ứng dụng của mình.

Từ bây giờ, tôi nghĩ, tôi nên thay đổi mô hình. Ai đó đã chỉ ra rằng ứng dụng Google IOSched là một ví dụ tuyệt vời về cách viết ứng dụng khách REST trên Android. Một số người khác nói rằng những cách này quá phức tạp.

Vì vậy, bất kỳ ai có thể vui lòng chỉ cho chúng tôi cách thực hành tốt nhất là gì? Nói một cách ngắn gọn và đơn giản.
Ứng dụng IOSched quá phức tạp đối với trường hợp sử dụng mẫu.


Xin chào, Nói chung tôi phát triển gói riêng cho dịch vụ web có tên "ws", tôi đã tổng quát hóa lớp có tên "WebServicUtils.java". Lớp WebServiceUtils.java có các phương thức để truy cập dịch vụ web. Tôi không chắc về kỹ thuật của mình là tốt nhất hay không nhưng Nó có thể tái sử dụng mỗi khi tôi sao chép gói ws của mình trong Ứng dụng Android, Hãy cho tôi biết nếu bạn muốn biết thêm về kỹ thuật của tôi.
Ketan Parmar

Tôi không nghĩ người bình luận trên youtube có giải pháp thay thế tốt hơn. Chúng tôi phải làm việc trong các API của Android, ngay cả khi chúng thường vô nghĩa quá phức tạp và dài dòng.
Timmmm

Lưu ý thêm, Mechanoid, một plugin eclipse mã nguồn mở cho Android có thể tạo các ứng dụng khách JSON-REST bằng cách sử dụng DSL đơn giản, hướng dẫn về cách sử dụng nó có thể được tìm thấy tại đây robotoworks.com/mechanoid-plugin/service-client-dsl (tôi là tác giả của plugin này, xin lỗi vì sự cắm không biết xấu hổ!)
Ian Warwick

Điều này có thể rất hữu ích cho những người đang học cách triển khai ứng dụng khách Android REST. Bản trình bày của Dobjanschi được chuyển thành PDF: drive.google.com/file/d/0B2dn_3573C3RdlVpU2JBWXdSb3c/…
Kay Zed

Câu trả lời:


99

CHỈNH SỬA 2 (tháng 10 năm 2017):

Đó là năm 2017. Chỉ cần sử dụng Retrofit. Hầu như không có lý do gì để sử dụng bất cứ thứ gì khác.

BIÊN TẬP:

Câu trả lời ban đầu là hơn một năm rưỡi tại thời điểm chỉnh sửa này. Mặc dù các khái niệm được trình bày trong câu trả lời gốc vẫn được giữ nguyên, như các câu trả lời khác đã chỉ ra, hiện nay có các thư viện giúp bạn thực hiện công việc này dễ dàng hơn. Quan trọng hơn, một số thư viện này xử lý các thay đổi cấu hình thiết bị cho bạn.

Câu trả lời gốc được giữ lại bên dưới để tham khảo. Nhưng cũng vui lòng dành thời gian để kiểm tra một số thư viện máy khách Rest dành cho Android để xem chúng có phù hợp với các trường hợp sử dụng của bạn hay không. Sau đây là danh sách một số thư viện mà tôi đã đánh giá. Nó hoàn toàn không nhằm mục đích trở thành một danh sách đầy đủ.


Câu trả lời gốc:

Trình bày cách tiếp cận của tôi để có khách hàng REST trên Android. Tôi không khẳng định nó là tốt nhất mặc dù :) Ngoài ra, hãy lưu ý rằng đây là những gì tôi đã đưa ra để đáp ứng yêu cầu của tôi. Bạn có thể cần phải có nhiều lớp / thêm độ phức tạp nếu trường hợp sử dụng của bạn yêu cầu nó. Ví dụ: tôi không có bộ nhớ cục bộ nào cả; vì ứng dụng của tôi có thể chịu được việc mất một vài phản hồi REST.

Phương pháp tiếp cận của tôi chỉ sử dụng AsyncTaskcác trang bìa. Trong trường hợp của tôi, tôi "gọi" các Tác vụ này từ Activityphiên bản của tôi ; nhưng để giải thích đầy đủ các trường hợp như xoay màn hình, bạn có thể chọn gọi chúng từService hoặc như vậy.

Tôi đã chọn ứng dụng khách REST của mình một cách có ý thức làm API. Điều này có nghĩa là ứng dụng sử dụng ứng dụng khách REST của tôi thậm chí không cần biết về URL REST thực và định dạng dữ liệu được sử dụng.

Khách hàng sẽ có 2 lớp:

  1. Lớp trên cùng: Mục đích của lớp này là cung cấp các phương thức phản ánh chức năng của API REST. Ví dụ: bạn có thể có một phương thức Java tương ứng với mọi URL trong API REST của bạn (hoặc thậm chí hai - một cho GET và một cho POST).
    Đây là điểm nhập vào API ứng dụng khách REST. Đây là lớp mà ứng dụng sẽ sử dụng bình thường. Nó có thể là một singleton, nhưng không nhất thiết.
    Phản hồi của cuộc gọi REST được lớp này phân tích cú pháp thành một POJO và trả về ứng dụng.

  2. Đây là AsyncTasklớp cấp thấp hơn , sử dụng các phương thức máy khách HTTP để thực sự đi ra ngoài và thực hiện cuộc gọi REST đó.

Ngoài ra, tôi đã chọn sử dụng cơ chế Gọi lại để thông báo kết quả AsyncTaskquay lại ứng dụng.

Văn bản đủ rồi. Bây giờ chúng ta hãy xem một số mã. Hãy lấy một URL REST API giả định - http://myhypotheticalapi.com/user/profile

Lớp trên cùng có thể trông như thế này:

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

}

Lưu ý rằng ứng dụng không sử dụng JSON hoặc XML (hoặc bất kỳ định dạng nào khác) do REST API trả về trực tiếp. Thay vào đó, ứng dụng chỉ nhìn thấy hạt đậu Profile.

Sau đó, lớp dưới (lớp AsyncTask) có thể trông như thế này:

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

Đây là cách một ứng dụng có thể sử dụng API (trong một Activityhoặc 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
            }
        });

Tôi hy vọng các ý kiến ​​là đủ để giải thích thiết kế; nhưng tôi rất vui khi cung cấp thêm thông tin.


Tôi thích câu trả lời này hơn do các ví dụ về mã khá đẹp. Cảm ơn
Marek Sebera

1
Có lẽ không có giá trị gì, điều này không thực sự tuân theo một mô hình RESTful MVC thích hợp, như được mô tả bởi Virgil Dobjanschi. Bạn sẽ cần kết hợp một lớp ContentProvider đầy đủ, lớp này sử dụng cơ sở dữ liệu SQLite mà ứng dụng trực tiếp sử dụng. Nếu không, đây là một ứng dụng khách REST nhẹ, tốt cho Android.
Cooper

1
Một điều nhỏ, bạn sẽ cần gọi thực thi trên Get / PostTask's đó
Mo Kargas 24/09/12

1
Điều này thực sự tuyệt vời. Làm cách nào để tôi làm cho GetResponseCallback chung chung hơn, để nó không chỉ chuyển lại một Hồ sơ hoặc bạn có đề xuất tạo một GetResponseCallback riêng biệt cho từng loại dữ liệu từ API không?

1
@MichaelHerbig Có, có nhiều cách để làm cho GetResponseCallbackchung chung hơn. Cái mà tôi thích là sử dụng giao diện đánh dấu : Thích interface IGetResopnse{} biểu thị tất cả các lớp có thể là phản hồi. Sau đó, tôi có class Profile implements IGetResponsevv Cuối cùng, làm GetResponseCallbackchung với IGetResponsenhư trên ràng buộc : public abstract class GetResponseCallback<? extends IGetResponse>.
curioustechizen

11

"Phát triển ứng dụng khách Android REST" của Virgil Dobjanschi đã dẫn đến nhiều cuộc thảo luận, vì không có mã nguồn nào được trình bày trong phiên hoặc được cung cấp sau đó.

Cách triển khai tham khảo duy nhất mà tôi biết (vui lòng bình luận nếu bạn biết thêm) hiện có tại Datadroid (phiên Google IO được đề cập dưới / trình bày). Nó là một thư viện mà bạn có thể sử dụng trong ứng dụng của riêng mình.

Liên kết thứ hai yêu cầu khuôn khổ REST "tốt nhất", được thảo luận nhiều về stackoverflow. Đối với tôi, kích thước ứng dụng là quan trọng, tiếp theo là hiệu suất của việc triển khai.

  • Thông thường, tôi sử dụng hàm nhập org.json thuần túy, là một phần của Android kể từ API cấp 1 và do đó không làm tăng kích thước ứng dụng.
  • Đối với tôi, rất thú vị là thông tin được tìm thấy về hiệu suất của trình phân tích cú pháp JSON trong các nhận xét: kể từ Android 3.0 Honeycomb, trình phân tích cú pháp trực tuyến của GSON được bao gồm dưới dạng android.util.JsonReader. Thật không may, các bình luận không có sẵn nữa.
  • Spring Android (đôi khi tôi sử dụng) hỗ trợ Jackson và GSON. Các tài liệu xuân Android RestTemplate Mô-đun điểm để một ứng dụng mẫu .

Do đó, tôi sử dụng org.json hoặc GSON cho các tình huống phức tạp hơn. Đối với kiến ​​trúc của triển khai org.json, tôi đang sử dụng một lớp tĩnh đại diện cho các trường hợp sử dụng máy chủ (ví dụ: findPerson, getPerson). Tôi gọi chức năng này từ một dịch vụ và sử dụng các lớp tiện ích đang thực hiện ánh xạ (dự án cụ thể) và mạng IO (mẫu REST của riêng tôi cho GET hoặc POST thuần túy). Tôi cố gắng tránh việc sử dụng phản xạ.


4
Cuốn sách O'Reilly, Lập trình Android, mô tả cách triển khai đầy đủ mô hình RESTful MVC của Dobjanschi (chương 12-13).
Cooper

Cảm ơn gợi ý: Tôi đã tìm thấy tuyên bố này trên Amazon: "Chương 12 và 13 đề cập đến các nhà cung cấp nội dung. Việc xử lý rộng rãi các nhà cung cấp nội dung với mã ví dụ và ứng dụng mẫu đã cung cấp cho tôi một số hiểu biết mới về cách hoạt động của công nghệ này và cách nó có thể được sử dụng trong các tình huống lập trình thực tế. Khung cung cấp nội dung để lưu trữ và tham chiếu dữ liệu bằng URI là một trong những tính năng mới của hệ điều hành Android. Công việc tuyệt vời trong việc giải thích từng bước công nghệ! "
ChrLipp

2
Mã này là trên github.com/bmeike/ProgrammingAndroid2Examples (nhưng chương bị thiếu, bạn có thể tìm thấy chúng trong các mã đầu tiên phiên bản github.com/bmeike/ProgrammingAndroidExamples )
ChrLipp

Có ai có thể lấy mã này chạy trên ICS + không? Tệp việc cần làm trong ví dụ FinchVideo nêu ngắn gọn "- Sự cố trong ICS". Tôi đã hơi thất vọng sau khi mua cuốn sách để khám phá mã ví dụ được chia ...
eageranalyst

7

Không bao giờ sử dụng AsynTask để thực hiện yêu cầu mạng hoặc bất cứ điều gì cần được duy trì. Async Task gắn chặt với hoạt động của bạn và nếu người dùng thay đổi hướng của màn hình kể từ khi tạo lại Ứng dụng, AsyncTask sẽ bị dừng.

Tôi khuyên bạn nên sử dụng Service pattern với Intent Service và ResultReceiver. Hãy xem RESTDroid . Đó là một thư viện cho phép bạn thực hiện bất kỳ loại yêu cầu REST nào một cách không đồng bộ và thông báo cho giao diện người dùng của bạn với Trình xử lý yêu cầu triển khai mẫu dịch vụ của Virgil Dobjanschi.


3

Có một thư viện khác với API sạch hơn nhiều và dữ liệu an toàn về kiểu. https://github.com/kodart/Httpzoid

Đây là một ví dụ sử dụng đơn giản

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

Hoặc phức tạp hơn với các lệnh gọi lại

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

Nó là mới, nhưng có vẻ rất hứa hẹn.


Có vẻ như nó đang chạy trên AsyncTask, điều không tốt cho các yêu cầu chạy lâu và chuyển đổi giữa các hoạt động, vì AsyncTask sẽ bị giết khi Activity thoát.
Malachiasz

1

Có rất nhiều thư viện ngoài đó và tôi đang sử dụng thư viện này: https://github.com/nerde/rest-resource . Cái này do tôi tạo ra và như bạn có thể thấy trong tài liệu, nó rõ ràng và đơn giản hơn những cái khác. Nó không tập trung vào Android, nhưng tôi đang sử dụng nó và nó hoạt động khá tốt.

Nó hỗ trợ HTTP Basic Auth. Nó thực hiện công việc bẩn thỉu là tuần tự hóa và giải mã hóa các đối tượng JSON. Bạn sẽ thích nó, đặc biệt nếu API của bạn giống như Rails.


1

Tuyên bố từ chối trách nhiệm: Tôi tham gia vào dự án mã nguồn mở rest2mobile

Một giải pháp thay thế khác làm ứng dụng khách REST là sử dụng rest2mobile .

Cách tiếp cận hơi khác vì nó sử dụng các ví dụ cụ thể về phần còn lại để tạo mã khách hàng cho dịch vụ REST. Mã thay thế URL REST và tải trọng JSON bằng các phương thức java và POJO gốc. Nó cũng tự động xử lý các kết nối máy chủ, lời gọi không đồng bộ và POJO đến / từ chuyển đổi JSON.

Lưu ý rằng công cụ này có nhiều loại khác nhau (cli, plugin, hỗ trợ android / ios / js) và bạn có thể sử dụng plugin android studio để tạo API trực tiếp vào ứng dụng của mình.

Tất cả mã có thể được tìm thấy trên github tại đây .


3
Vui lòng thay thế liên kết đầu tiên bằng mục tiêu thực tế thay vì quảng cáo trang web của bạn.
Skydan

0

Chúng tôi đã tạo nguồn mở thư viện ứng dụng khách REST không đồng bộ nhẹ của mình dành cho Android, bạn có thể thấy nó hữu ích nếu bạn có yêu cầu tối thiểu và không muốn tự xử lý đa luồng - ứng dụng này rất tốt cho các giao tiếp cơ bản nhưng không phải là ứng dụng khách REST đầy đủ thư viện.

Nó được gọi là libRESTfulClient và có thể được tìm thấy trên GitHub .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.