Клиент отдыха андроида, образец?


даже если этот поток принял ответ, не стесняйтесь предлагать другие идеи, вы используете или любите


Я встречал эти статьи:

и это привело меня к этому Google I / O 2010 видео о клиенте REST приложения

с этого момента я создаю компонент REST как статический компонент в своем классе контроллера приложений.

с этого момента, я думаю, я должен изменить шаблон. кто-то указал, что Google IOSched приложение является отличным примером того, как писать отдых клиентов на Android. кто-нибудь сказали, что этот способ слишком усложнен.

Итак, может ли кто-нибудь показать нам, что такое лучшая практика? Вкратце и простым способом.
Приложение IOSched слишком сложно для примера использования.

6 108

6 ответов:

EDIT 2 (октябрь 2017):

Это 2017. Просто используйте дооснащение. Там почти нет причин использовать что-либо еще.

EDIT:

оригинальный ответ составляет более полутора лет на момент этого редактирования. Хотя концепции, представленные в оригинальном ответе, все еще сохраняются, как указывают другие ответы, теперь есть библиотеки, которые облегчают эту задачу для вас. Что еще более важно, некоторые из этих библиотек обрабатывают изменения конфигурации устройства для тебя.

исходный ответ сохраняется ниже Для справки. Но, пожалуйста, также найдите время, чтобы изучить некоторые из остальных клиентских библиотек для Android, чтобы увидеть, если они соответствуют вашим случаям использования. Ниже приведен список некоторых библиотек, которые я оценил. Это отнюдь не исчерпывающий список.


Оригинальный Ответ:

представляя мой подход к тому, чтобы отдыхать клиентов на Android. Я не утверждаю, что это лучший, хотя :) кроме того, обратите внимание, что это то, что я придумал в ответ на мое требование. Возможно, вам потребуется больше слоев/добавить больше сложности, если ваш вариант использования требует этого. Например, у меня нет локальное хранилище вообще; потому что мое приложение может терпеть потерю нескольких ответов REST.

мой подход использует только AsyncTask s под одеялом. В моем случае, я "называю" эти задачи от моего Activity экземпляр; но для полного учета случаев, таких как поворот экрана, вы можете выбрать, чтобы вызвать их из Service или такой.

Я сознательно выбрал свой клиент REST сам, чтобы быть API. Это означает, что приложение, которое использует мой клиент REST, даже не должно знать о фактическом URL-адресе REST и используемый формат данных.

клиент будет иметь 2 слоя:

  1. верхний слой: целью этого слоя является предоставление методов, которые отражают функциональность REST API. Например, у вас может быть один метод Java, соответствующий каждому URL - адресу в вашем REST API (или даже два-один для GETs и один для POSTs).
    Это точка входа в клиентский API-интерфейс REST. Это слой, который приложение будет использовать обычно. Это может быть синглтон, но нет обязательно.
    Ответ на вызов REST анализируется этим слоем в POJO и возвращается в приложение.

  2. это нижний уровень AsyncTask слой, который использует методы HTTP-клиента, чтобы фактически выйти и сделать этот вызов REST.

кроме того, я решил использовать механизм обратного вызова, чтобы сообщить результат AsyncTasks вернуться к приложению.

достаточно текста. Давайте посмотрим код сейчас. Давайте возьмем гипотетический REST API URL -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
            }
        });

Я надеюсь, что комментарии достаточно, чтобы объяснить дизайн; но я был бы рад предоставить больше информации.

" разработка клиентских приложений для Android REST " Вирджила Добьянски вызвала много дискуссий, поскольку исходный код не был представлен во время сессии или был предоставлен позже.

единственная эталонная реализация, которую я знаю (пожалуйста, прокомментируйте, если вы знаете больше), доступна по адресу Datadroid (сеанс ввода-вывода Google упоминается в разделе / презентация). Это библиотека, которую вы можете использовать в своем собственном приложении.

вторая ссылка запрашивает" лучший " отдых фреймворк, который активно обсуждается на stackoverflow. Для меня важен размер приложения, а затем производительность реализации.

  • обычно я использую простую организацию.имплантация json, которая является частью Android с уровня API 1 и поэтому не увеличивает размер приложения.
  • для меня очень интересной была информация, найденная на производительность парсеров JSON в комментариях: начиная с Android 3.0 Honeycomb, потоковая передача GSON парсер включен в качестве android.утиль.JsonReader. К сожалению, комментарии больше не доступны.
  • Spring Android (который я иногда использую) поддерживает Jackson и GSON. Элемент Spring Android RestTemplate модуль документация точки образец приложение.

поэтому я придерживаюсь орг.json или GSON для более сложных сценариев. Для архитектуры организации.реализация JSON, я использую статический класс, который представляет использование сервера случаи (например, findPerson, getPerson). Я вызываю эту функциональность из службы и использую служебные классы, которые выполняют сопоставление (специфичное для проекта) и сетевой IO (мой собственный шаблон REST для простого GET или POST). Я стараюсь избегать использования отражения.

никогда не используйте AsynTask для выполнения сетевого запроса или того, что нужно сохранить. Асинхронные задачи сильно привязаны к вашей деятельности, и если пользователь изменит ориентацию экрана с момента повторного создания приложения, AsyncTask будет остановлен.

Я предлагаю вам использовать шаблон службы с намерением службы и ResultReceiver. Взгляните на RESTDroid. Это библиотека, которая позволяет выполнять любые запросы REST асинхронно и уведомлять свой пользовательский интерфейс с помощью Запрос слушателей реализации модели Вергилия Dobjanschi услуг.

есть еще одна библиотека с гораздо более чистым API и типобезопасными данными. https://github.com/kodart/Httpzoid

вот простой пример использования

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

или более сложные с ответами

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

Это свежий новый, но выглядит очень многообещающе.

есть много библиотек там, и я использую этот:https://github.com/nerde/rest-resource это было создано мной, и, как вы можете видеть в документации, это намного чище и проще, чем другие. Он не ориентирован на Android, но я использую его, и он работает довольно хорошо.

Он поддерживает HTTP Basic Auth. Он выполняет грязную работу по сериализации и десериализации объектов JSON. Вам понравится, особенно если ваш API-это Rails как.

отказ от ответственности: я участвую в проекте rest2mobile с открытым исходным кодом

Другой альтернативой в качестве клиента REST является использование rest2mobile.

подход немного отличается, поскольку он использует бетон примеры остальных для создания клиентского кода для службы REST. Код заменяет полезные нагрузки REST URL и JSON собственными методами java и POJOs. Он также автоматически обрабатывает соединения с сервером, асинхронные вызовы и POJO to / from Преобразования в JSON.

обратите внимание, что этот инструмент поставляется в разных вариантах (cli, Плагины, поддержка android / ios / js), и вы можете использовать Android studio plugin для создания API непосредственно в вашем приложении.

весь код можно найти на github здесь.