Клиентская библиотека REST API для Android

Мы создаем приложение для обмена сообщениями на основе местоположения, которое использует Parse.com в качестве серверной части (Parse.com похож на Urban Airship/PubNub и т. д.), и теперь мы хотим переключиться на нашу собственную серверную часть для лучшего контроля. Для этого мы создали серверную часть на основе node.js с функциональностью, доступной через REST API.

Чтобы использовать этот API, мы хотим создать библиотеку Android (аналогичную Android SDK от Parse.com), который абстрагирует все HTTP-запросы/ответы или вызовы REST API и предоставляет прямые функции для различных операций, таких как getUsers(), sendMessage() и т. д.

Способы реализации клиента REST API в Android:

Теперь, учитывая, что мы хотим создать библиотеку Android и возможны одновременные вызовы REST API, когда пользователь взаимодействует с приложением, какой подход лучше всего использовать? Я также открыт для других предложений/рекомендаций.

ОБНОВЛЕНИЕ. Сначала мы создали собственную библиотеку, используя IntentService + ResultReceiver, которая работала нормально. Но позже мы наткнулись на Android Async Http. Используй это. Это потрясающе!


person Madhur    schedule 18.11.2012    source источник
comment
+1 для Android Async Http.   -  person Chris Rae    schedule 26.09.2013
comment
спасибо за Async Http спасибо за внимание к тому же человеку!   -  person vishal dharankar    schedule 16.06.2015


Ответы (6)


Лучшая реализация, которую я видел на основе советов Google IO Pro 2010, — это библиотека RoboSpice, которая основана на REST и очень умно работает с жизненным циклом Activity, чтобы не допустить утечки памяти.

Краткая информация о библиотеке здесь

  • Загрузчики предназначены для базы данных, а не для REST, они сбрасываются при сбросе активности, что означает, что вы теряете свои данные.
  • Асинхронная задача, просто нет.
  • Intent Service + Result Receiver — это в основном то, как работает RoboSpice, поэтому, если вы создаете свою собственную библиотеку, я бы выбрал этот подход!
  • Служба также хороша, похожа на метод IntentService, но в данном случае IntentService работает немного лучше.

Метод Service может быть лучше, посмотрите на сервис robospice, они используют ExecutorService, который завершает Service, когда он исчерпал Requests для работы, это больше параллелизм Java, чем специфичный для Android. Главное отметить, что служба работает во время обработки запросов, а затем завершает работу, если их не осталось.

Преимущество использования пула потоков ExecutorService или любого другого типа заключается в том, что вы можете определить, сколько запросов вы можете выполнять одновременно. если у вас нет очень быстрого соединения, 2-4 - это самое большее, что я когда-либо предлагал.

person Chris.Jenkins    schedule 18.11.2012
comment
Спасибо :) Это действительно облегчает решение. Но теперь у меня есть еще один вопрос, учитывая, что мы будем использовать IntentService. Поскольку IntenetServe обрабатывает только один запрос за раз, а новые запросы ставятся в очередь, как мы можем выполнять одновременные вызовы REST API? Скажем, если список пользователей извлекается (что занимает ~ 10 секунд), и пользователь пытается отправить сообщение между этой операцией? - person Madhur; 19.11.2012
comment
Либо ваша собственная версия IntentService, либо Accept для выполнения одного запроса за раз, Google изменил множество потоков в Android SDK, чтобы теперь выполнять их по одному. Если вам это не нужно сейчас, принятое соглашение просто обрабатывает очередь «задач». Говоря это, я думаю, что RoboSpice делает несколько запросов одновременно, взгляните на их источник. - person Chris.Jenkins; 19.11.2012
comment
Один уродливый подход, о котором я могу думать, - это реализация нескольких IntentService, которые в основном выполняют одну и ту же операцию вызова REST API. Таким образом, мы можем делать одновременные запросы, но это добавит много избыточности кода. Ваши мысли по этому поводу? - person Madhur; 19.11.2012
comment
Да, я бы не стал использовать множественный метод IntentService, но... вы можете использовать IntentService, который передает его другому потоку, IntentService будет двигаться дальше, как только вы передадите его потоку IntentService. - person Chris.Jenkins; 19.11.2012
comment
Вы имеете в виду AsyncTask в IntentService? Не могли бы вы рассказать, как это можно реализовать с помощью материалов, предоставляемых Android? - person Madhur; 19.11.2012
comment
Обновленный ответ, Service + ThreadPool/ExecutorService может быть лучшим вариантом. - person Chris.Jenkins; 20.11.2012
comment
@Chris.Jenkins Ссылка на сервис RoboSpice дает 404. - person Stephane; 11.12.2013
comment
@StephaneEybert Исправлена ​​ссылка на сервис специй, спасибо за предупреждение. - person Chris.Jenkins; 16.12.2013

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

Документация достаточно полная, чтобы легко писать код.

CQFD > действуй

person Hugo Gresse    schedule 08.12.2014

МОЖЕТ БЫТЬ ЭТОТ КЛАСС МОЖЕТ ПОМОЧЬ:-

/*Copyright 2014 Bhavit Singh Sengar
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.*/

package com.infotech.zeus.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;
import android.widget.Toast;

public class RestClient {


        JSONObject data = new JSONObject();
        String url;
        String headerName;
        String headerValue;

        public RestClient(String s){

            url = s;
        }


        public void addHeader(String name, String value){

            headerName = name;
            headerValue = value;

        }

        public void addParam(String key, String value){

            try {
                data.put(key, value);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


        }

        public String executePost(){  // If you want to use post method to hit server

            HttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader(headerName, headerValue);
            HttpResponse response = null;
            String result = null;
            try {
                StringEntity entity = new StringEntity(data.toString(), HTTP.UTF_8);
                httpPost.setEntity(entity);
                response = httpClient.execute(httpPost);
                HttpEntity entity1 = response.getEntity();
                result = EntityUtils.toString(entity1);
                return result;
                //Toast.makeText(MainPage.this, result, Toast.LENGTH_LONG).show();
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return result;



        }

        public String executeGet(){ //If you want to use get method to hit server

            HttpClient httpClient = new DefaultHttpClient();
            HttpGet httpget = new HttpGet(url);
            String result = null;
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            try {
                result = httpClient.execute(httpget, responseHandler);
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return result;
        }
}

ПРОСТОЙ ПРИМЕР ИСПОЛЬЗОВАНИЯ ЭТОГО КЛАССА:

RestClient client = new RestClient("http://www.example.com/demo.php");  //Write your url here
        client.addParam("Name", "Bhavit"); //Here I am adding key-value parameters
        client.addParam("Age", "23");

        client.addHeader("content-type", "application/json"); // Here I am specifying that the key-value pairs are sent in the JSON format

        try {
            String response = client.executePost(); // In case your server sends any response back, it will be saved in this response string.

        } catch (Exception e) {
            e.printStackTrace();
        }
person Bhavit S. Sengar    schedule 09.04.2014
comment
Это отличный класс, за исключением того, что СЕЙЧАС у вас есть устаревшие ошибки, возможно, замена будет полезна. - person flakerimi; 13.04.2019

Вы также можете использовать RESTDroid. Он очень похож на RoboSpice, но проще в использовании (хотя и менее мощный).

Если вы создаете модуль Parse.com для RESTDroid, не стесняйтесь добавлять его на GitHub!

person Pierre Criulanscy    schedule 13.02.2013

Если я могу добавить еще одну вещь, я недавно начал писать хорошую библиотеку для реализации движков (используемых MKNetworkKit в iOS) и команд для связи с REST API для Android. Может быть полезно для тех, кто пытается получить доступ к REST API. https://github.com/m2d2/MDBaseAndroidLibraries

person dineth    schedule 04.02.2013

Вы также можете попробовать Аннотации Android с rest-spring плагин для автоматического выполнения этих задач.

Они используют оболочку spring framework для Android и обеспечивают действительно хороший способ обработки rest api.

Примеры:

Замените AsyncTask -> doInBackground() аннотацией @Background:

@Background
protected void backgroundWork(){
    // do something in background
}

Замените runOnUiThread, onPostExecute() на @UiThread

@UiThread
protected void uiWork(){
    // do something on UI Thread
}

Для Rest API

создать оставшийся клиент:

@Rest(rootUrl = "http://company.com/ajax/services",
      converters = { MappingJackson2HttpMessageConverter.class })
public interface MyRestClient {

    @Get("/events")
    EventList getEvents();
}

использовать оставшийся клиент:

@RestClient
MyRestClient myRestClient;

public void showAllEvents(){
    EventList list = myRestClient.getEvents();
    // do something with this list

}
person Community    schedule 06.05.2016
comment
getForObject,getForEntity можно использовать для простого распределения данных по объектам. Для getForObject использование Jackson - ObjectMapper значительно упрощает жизнь с необязательным атрибутом. - person Abhijeet; 03.06.2016