【问题标题】:REST API Client Library for Android适用于 Android 的 REST API 客户端库
【发布时间】:2012-11-18 20:11:39
【问题描述】:

我们正在构建一个使用 Parse.com 作为后端的基于位置的消息传递应用程序 (Parse.com 类似于 Urban Airship/PubNub 等),我们现在想切换到我们自己的后端以获得更好的控制。为此,我们构建了一个基于 node.js 的后端,其功能通过 REST API 公开

为了使用这个 API,我们想要构建一个 Android 库(类似于Parse.com's Android SDK),它抽象了所有 HTTP 请求/响应或 REST API 调用,并为各种操作提供直接函数,如 getUsers()、sendMessage()、等等

在 Android 中实现 REST API 客户端的方式:

现在,考虑到我们要构建一个 android 库,并且在用户与应用程序交互时可能会同时调用 REST API,哪种方法最好继续进行?我也愿意接受其他建议/建议。

更新:我们首先使用 IntentService + ResultReceiver 构建了自己的库,效果很好。但我们后来偶然发现了Android Async Http。用它。太棒了!

【问题讨论】:

  • +1 用于 Android 异步 Http。
  • 感谢 Async Http 感谢同一个人的提醒!

标签: android rest asynchronous android-library intentservice


【解决方案1】:

我见过的基于 Google IO Pro Tips 2010 的最佳实现是 RoboSpice 库,它基于 REST 并且非常巧妙地与 Activity 生命周期配合使用,不会泄漏内存。

infographic图书馆是here

  • 加载程序是为数据库设计的,而不是 REST,它们会在活动重置时重置,这意味着您会丢失数据。
  • 异步任务,没有。
  • Intent Service + Result 接收器基本上是 RoboSpice 的工作方式,所以如果您正在构建自己的库,我会采用这种方法!
  • Service 也不错,类似于 IntentService 方法,但 IntentService 在这种情况下效果更好。

Service 方法可能更好,look at the robospice service 他们使用ExecutorService 来终止Service,当它用完Requests 时,这比Android 特定的Java 并发性更多。主要需要注意的是,服务在处理请求时运行,然后如果没有请求,则终止自身。

使用ExecutorService 或任何类型的线程池的优点是您可以定义一次可以运行多少个请求。除非您的连接速度非常快,否则我建议最多使用 2-4 个。

【讨论】:

  • 谢谢 :) 这确实使决定更容易。但现在我还有一个问题,考虑到我们将使用 IntentService,因为 IntenetServe 一次只处理一个请求并且新请求排队,我们如何进行同时 REST API 调用?比如说,如果正在检索用户列表(大约需要 10 秒)并且用户尝试在该操作之间发送消息?
  • 无论是您自己的 IntentService 版本还是 Accept 一次运行一个请求,Google 已经更改了 Android SDK 中的许多线程,现在一次只运行一个。除非您现在需要它,否则公认的约定只是处理“任务”队列。话虽如此,我认为 RoboSpice 会同时执行几个请求,看看它们的来源。
  • 我能想到的一种丑陋的方法是实现多个 IntentService,它们基本上执行调用 REST API 的相同操作。这样,我们可以同时发出请求,但会增加很多代码冗余。您对此有何看法?
  • 是的,我会避免使用多个 IntentService 方法,但是...您可以使用 IntentService 将其传递给另一个线程,然后 IntentService 将在您传递它后继续IntentService 线程。
  • 更新答案,Service + ThreadPool/ExecutorService 可能是最好的选择。
【解决方案2】:

我使用过Retrofit,它是一个非常好的库,它为管理端点和解析数据/集合/对象提供了一个简单的结构。

文档足够完整,可以轻松编写代码。

CQFD > 去吧

【讨论】:

    【解决方案3】:

    这门课可能会有所帮助:-

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

    【讨论】:

    • 这是一个很棒的课程,除了现在你有已弃用的错误,也许替换会有所帮助。
    【解决方案4】:

    您也可以使用RESTDroid。它与 RoboSpice 非常相似,但使用起来更简单(尽管功能也较弱)。

    如果您为 RESTDroid 创建 Parse.com 模块,请不要犹豫,将其添加到 GitHub 上!

    【讨论】:

      【解决方案5】:

      如果我可以再补充一点,我最近开始编写一个不错的库来实现引擎(在 iOS 中被 MKNetworkKit 使用)和命令来与 Android 的 REST API 进行通信。可能对任何尝试使用 REST API 的人有所帮助。 https://github.com/m2d2/MDBaseAndroidLibraries

      【讨论】:

        【解决方案6】:

        您也可以尝试使用 Android Annotationsrest-spring 插件来自动完成这些任务。

        他们在 spring framework for android 上使用了一个包装器,并提供了一种非常好的方法来处理 rest apis

        示例:

        将 AsyncTask -> doInBackground() 替换为 @Background 注释:

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

        用@UiThread 替换runOnUiThread、onPostExecute()

        @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
        
        }
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-19
        • 2020-05-08
        • 1970-01-01
        • 1970-01-01
        • 2016-08-19
        • 2017-06-25
        • 2013-02-21
        • 2014-08-06
        相关资源
        最近更新 更多