[转]Volley的功能及设置

olley提供了优美的框架,使android程序网络访问更容易、更快。

Volley抽象实现了底层的HTTP Client库,我们不需关注HTTP Client细节,专注于写出更加漂亮、干净的RESTful HTTP请求。

Volley请求会异步执行,不阻挡主线程。

Volley提供的功能

  1. 封装了异步的RESTful请求API
  2. 一个优雅and稳健的请求队列
  3. 一个可扩展的架构,使开发者能实现自定义的请求和响应处理机制
  4. 能使用外部Http Client库
  5. 缓存策略
  6. 自定义的网络图像加载视图(NetworkImageView,ImageLoader等)

为什么使用异步Http请求

Android中要求HTTP请求异步执行,如果在主线程执行HTTP请求,可能会抛出 android.os.NetworkOnMainThreadException  异常。阻塞主线程有一些严重的后果,它阻碍UI渲染,用户体验不流 畅,它可能会导致可怕的ANR(Application Not Responding)。要避免这些陷阱,作为一个开发者,应该始终确保HTTP请求是在一个不同的线程

怎样使用Volley

1、安装和使用Volley库

2、使用请求队列

3、异步的JSON、String请求

4、取消请求

5、重试失败的请求,自定义请求超时

6、设置请求头(HTTP headers)

7、使用Cookies

8、错误处理

1.安装和使用Volley库

引入Volley非常简单,首先,从git库先克隆一个下来:

git clone https://android.googlesource.com/platform/frameworks/volley

然后编译为jar包,再把jar包放到自己的工程的libs目录。

2.使用请求队列

Volley的所有请求都放在一个队列,然后进行处理,这里是你如何将创建一个请求队列:

 RequestQueue mRequestQueue = Volley.newRequestQueue(this); // ‘this‘ is Context

理想的情况是把请求队列集中放到一个地方,最好是初始化应用程序类中初始化请求队列,下面类做到了这一点:

public class ApplicationController extends Application {    /**
     * Log or request TAG     */
    public static final String TAG = "VolleyPatterns";    /**
     * Global request queue for Volley     */
    private RequestQueue mRequestQueue;    /**
     * A singleton instance of the application class for easy access in other places     */
    private static ApplicationController sInstance;

    @Override    public void onCreate() {        super.onCreate();        // initialize the singleton
        sInstance = this;
    }    /**
     * @return ApplicationController singleton instance     */
    public static synchronized ApplicationController getInstance() {        return sInstance;
    }    /**
     * @return The Volley Request queue, the queue will be created if it is null     */
    public RequestQueue getRequestQueue() {        // lazy initialize the request queue, the queue instance will be        // created when it is accessed for the first time
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }        return mRequestQueue;
    }    /**
     * Adds the specified request to the global queue, if tag is specified
     * then it is used else Default TAG is used.
     * 
     * @param req
     * @param tag     */
    public <T> void addToRequestQueue(Request<T> req, String tag) {        // set the default tag if tag is empty
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);

        VolleyLog.d("Adding request to queue: %s", req.getUrl());

        getRequestQueue().add(req);
    }    /**
     * Adds the specified request to the global queue using the Default TAG.
     * 
     * @param req
     * @param tag     */
    public <T> void addToRequestQueue(Request<T> req) {        // set the default tag if tag is empty        req.setTag(TAG);

        getRequestQueue().add(req);
    }    /**
     * Cancels all pending requests by the specified TAG, it is important
     * to specify a TAG so that the pending/ongoing requests can be cancelled.
     * 
     * @param tag     */
    public void cancelPendingRequests(Object tag) {        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}

3.异步的JSON、String请求

Volley提供了以下的实用工具类进行异步HTTP请求:

JsonObjectRequest — To send and receive JSON Object from the Server

JsonArrayRequest — To receive JSON Array from the Server

StringRequest — To retrieve response body as String (ideally if you intend to parse the response by yourself)

JsonObjectRequest

这个类可以用来发送和接收JSON对象。这个类的一个重载构造函数允许设置适当的请求方法(DELETE,GET,POST和PUT)。如果您正在使用一个RESTful服务端,可以使用这个类。下面的示例显示如何使GET和POST请求

GET请求:

final String URL = "/volley/resource/12";// pass second argument as "null" for GET requestsJsonObjectRequest req = new JsonObjectRequest(URL, null,       new Response.Listener<JSONObject>() {
           @Override           public void onResponse(JSONObject response) {               try {
                   VolleyLog.v("Response:%n %s", response.toString(4));
               } catch (JSONException e) {
                   e.printStackTrace();
               }
           }
       }, new Response.ErrorListener() {
           @Override           public void onErrorResponse(VolleyError error) {
               VolleyLog.e("Error: ", error.getMessage());
           }
       });// add the request object to the queue to be executedApplicationController.getInstance().addToRequestQueue(req);

POST请求:

final String URL = "/volley/resource/12";// Post params to be sent to the serverHashMap<String, String> params = new HashMap<String, String>();
params.put("token", "AbCdEfGh123456");

JsonObjectRequest req = new JsonObjectRequest(URL, new JSONObject(params),       new Response.Listener<JSONObject>() {
           @Override           public void onResponse(JSONObject response) {               try {
                   VolleyLog.v("Response:%n %s", response.toString(4));
               } catch (JSONException e) {
                   e.printStackTrace();
               }
           }
       }, new Response.ErrorListener() {
           @Override           public void onErrorResponse(VolleyError error) {
               VolleyLog.e("Error: ", error.getMessage());
           }
       });// add the request object to the queue to be executedApplicationController.getInstance().addToRequestQueue(req);

JsonArrayRequest

这个类可以用来接受 JSON Arrary,不支持JSON Object。这个类现在只支持 HTTP GET。由于支持GET,你可以在URL的后面加上请求参数。类的构造函数不支持请求参数

final String URL = "/volley/resource/all?count=20";
JsonArrayRequest req = new JsonArrayRequest(URL, new Response.Listener<JSONArray> () {
    @Override    public void onResponse(JSONArray response) {        try {
            VolleyLog.v("Response:%n %s", response.toString(4));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}, new Response.ErrorListener() {
    @Override    public void onErrorResponse(VolleyError error) {
        VolleyLog.e("Error: ", error.getMessage());
    }
});// add the request object to the queue to be executedApplicationController.getInstance().addToRequestQueue(req);

StringRequest

这个类可以用来从服务器获取String,如果想自己解析请求响应可以使用这个类,例如返回xml数据。它还可以使用重载的构造函数定制请求

final String URL = "/volley/resource/recent.xml";
StringRequest req = new StringRequest(URL, new Response.Listener<String>() {
    @Override    public void onResponse(String response) {
        VolleyLog.v("Response:%n %s", response);
    }
}, new Response.ErrorListener() {
    @Override    public void onErrorResponse(VolleyError error) {
        VolleyLog.e("Error: ", error.getMessage());
    }
});// add the request object to the queue to be executedApplicationController.getInstance().addToRequestQueue(req);

4.取消请求

Volley提供了强大的API取消未处理或正在处理的请求。取消请求最简单的方法是调用请求队列cancelAll(tag)的方法,前提是你在添加请求时设置了标记。这样就能使标签标记的请求挂起。

给请求设置标签:

request.setTag("My Tag");

使用ApplicationController添加使用了标签的请求到队列中:

ApplicationController.getInstance().addToRequestQueue(request, "My Tag");

取消所有指定标记的请求:

mRequestQueue.cancelAll("My Tag");

5.重试失败的请求,自定义请求超时

Volley中没有指定的方法来设置请求超时时间,可以设置RetryPolicy 来变通实现。DefaultRetryPolicy类有个initialTimeout参数,可以设置超时时间。要确保最大重试次数为1,以保证超时后不重新请求。

Setting Request Timeout

request.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 1, 1.0f));

设置请求头(HTTP headers)        如果你想失败后重新请求(因超时),您可以指定使用上面的代码,增加重试次数。注意最后一个参数,它允许你指定一个退避乘数可以用来实现“指数退避”来从RESTful服务器请求数据。

有时候需要给HTTP请求添加额外的头信息,一个常用的例子是添加 “Authorization”到HTTP 请求的头信息。Volley请求类提供了一个 getHeaers()的方法,重载这个方法可以自定义HTTP 的头信息。

添加头信息:

JsonObjectRequest req = new JsonObjectRequest(URL, new JSONObject(params),           new Response.Listener<JSONObject>() {
               @Override               public void onResponse(JSONObject response) {                   // handle response               }
           }, new Response.ErrorListener() {
               @Override               public void onErrorResponse(VolleyError error) {                   // handle error                                       }
           }) {

       @Override       public Map<String, String> getHeaders() throws AuthFailureError {
           HashMap<String, String> headers = new HashMap<String, String>();
           headers.put("CUSTOM_HEADER", "Yahoo");
           headers.put("ANOTHER_CUSTOM_HEADER", "Google");           return headers;
       }
   };

6.使用Cookies

Volley中没有直接的API来设置cookies,Volley的设计理念就是提供干净、简洁的API来实现RESTful HTTP请求,不提供设置cookies是合理的。

下面是修改后的ApplicationController类,这个类修改了getRequestQueue()方法,包含了 设置cookie方法,这些修改还是有些粗糙

// http client instanceprivate DefaultHttpClient mHttpClient;public RequestQueue getRequestQueue() {    // lazy initialize the request queue, the queue instance will be    // created when it is accessed for the first time
    if (mRequestQueue == null) {        // Create an instance of the Http client. 
        // We need this in order to access the cookie store
        mHttpClient = new DefaultHttpClient();        // create the request queue
        mRequestQueue = Volley.newRequestQueue(this, new HttpClientStack(mHttpClient));
    }    return mRequestQueue;
}/**
 * Method to set a cookie */public void setCookie() {
    CookieStore cs = mHttpClient.getCookieStore();    // create a cookie
    cs.addCookie(new BasicClientCookie2("cookie", "spooky"));
}// add the cookie before adding the request to the queuesetCookie();// add the request to the queuemRequestQueue.add(request);

7.错误处理

正如前面代码看到的,在创建一个请求时,需要添加一个错误监听onErrorResponse。如果请求发生异常,会返回一个VolleyError实例。

以下是Volley的异常列表:

AuthFailureError:如果在做一个HTTP的身份验证,可能会发生这个错误。

NetworkError:Socket关闭,服务器宕机,DNS错误都会产生这个错误。

NoConnectionError:和NetworkError类似,这个是客户端没有网络连接。

ParseError:在使用JsonObjectRequest或JsonArrayRequest时,如果接收到的JSON是畸形,会产生异常。

SERVERERROR:服务器的响应的一个错误,最有可能的4xx或5xx HTTP状态代码。

TimeoutError:Socket超时,服务器太忙或网络延迟会产生这个异常。默认情况下,Volley的超时时间为2.5秒。如果得到这个错误可以使用RetryPolicy。

可以使用一个简单的Help类根据这些异常提示相应的信息:

public class VolleyErrorHelper {     /**
     * Returns appropriate message which is to be displayed to the user 
     * against the specified error object.
     * 
     * @param error
     * @param context
     * @return
     */
  public static String getMessage(Object error, Context context) {      if (error instanceof TimeoutError) {          return context.getResources().getString(R.string.generic_server_down);
      }      else if (isServerProblem(error)) {          return handleServerError(error, context);
      }      else if (isNetworkProblem(error)) {          return context.getResources().getString(R.string.no_internet);
      }      return context.getResources().getString(R.string.generic_error);
  }  
  /**
  * Determines whether the error is related to network
  * @param error
  * @return
  */
  private static boolean isNetworkProblem(Object error) {      return (error instanceof NetworkError) || (error instanceof NoConnectionError);
  }  /**
  * Determines whether the error is related to server
  * @param error
  * @return
  */
  private static boolean isServerProblem(Object error) {      return (error instanceof ServerError) || (error instanceof AuthFailureError);
  }  /**
  * Handles the server error, tries to determine whether to show a stock message or to 
  * show a message retrieved from the server.
  * 
  * @param err
  * @param context
  * @return
  */
  private static String handleServerError(Object err, Context context) {
      VolleyError error = (VolleyError) err;
  
      NetworkResponse response = error.networkResponse;  
      if (response != null) {          switch (response.statusCode) {            case 404:            case 422:            case 401:                try {                    // server might return error like this { "error": "Some error occured" }                    // Use "Gson" to parse the result
                    HashMap<String, String> result = new Gson().fromJson(new String(response.data),                            new TypeToken<Map<String, String>>() {
                            }.getType());                    if (result != null && result.containsKey("error")) {                        return result.get("error");
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }                // invalid request
                return error.getMessage();            default:                return context.getResources().getString(R.string.generic_server_down);
            }
      }        return context.getResources().getString(R.string.generic_error);
  }
}

总结:

Volley是一个非常好的库,你可以尝试使用一下,它会帮助你简化网络请求,带来更多的益处。

我也希望更加全面的介绍Volley,以后可能会介绍使用volley加载图像的内容,欢迎关注

时间: 2024-11-09 04:39:00

[转]Volley的功能及设置的相关文章

转:Eclipse自动补全功能轻松设置

Eclipse自动补全功能轻松设置 || 不需要修改编辑任何文件 2012-03-08 21:29:02|  分类: Java |  标签:eclipse  自动补全  设置  |举报|字号 订阅 下载LOFTER我的照片书  | 本文介绍如何设置Eclipse代码自动补全功能.轻松实现输入任意字母均可出现代码补全提示框. Eclipse代码自动补全功能默认只包括 点"."  ,即只有输入”."后才出现自动补全的提示框.想要自动补全总是去按 “Alt + / ”也很麻烦. 其

Eclipse自动补全功能轻松设置

Eclipse自动补全功能轻松设置 1.打开Eclipse->Window->Perferences 2.找到Java下的Editor下的Content Assist,右边出现的选项中,有一个Auto activation triggers for Java,会看到只有一个"."存在.表示:只有输入"."之后才会有代码提示,然后将其修改为abcdefghijklmnopqrstuvwxyz..如下图所示: 参考: 如何设置eclipse代码自动提示功能

squid的配置及功能的设置

squid正向代理正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端.客户端才能使用正向代理.从某种意义上说,"客户端和正向代理服务器像是位于同一个局域网".正向代理服务器的主要目的是缓存数据来响应客户端的 HTTP 请求,一般都会进行用户访问控制,使用时需要在浏览器中进行 IP 和端口设置.正向代理的典型用途是为在防火墙

Android Volley 的基本使用/设置HTTP请求参数、apikey

最近在做一个Android的新闻客户端,感觉收获颇丰. 这里分享一下Volley获取网络数据的方法 Volley是Google I/O 2013推出的网络通信库,它的拓展性很强,使用它能使代码变得更健壮,Volley在提供了高性能网络通讯功能的同时,对网络图片加载也提供了良好的支持 下面主要介绍一下Volley的StringRequest的使用方法 简单的写法是这样的: 1 /** 2 * 获取网络数据 新闻卡片 3 */ 4 private void getNewsData(String Ne

android项目 之 记事本(10) ----- 手写功能之设置画笔大小和画笔颜色

上一节,实现了画板的所有功能,包括设置画笔大小,设置画笔颜色,橡皮擦等功能,而手写,也可以添加设置笔迹大小和颜色的功能,这节就顺势实现手写的调整笔迹大小和调整笔迹的颜色. 先看图: 其实,手写和画板的这些功能都类似,直接复用之前的代码就行,原理如下:      1. 设置画笔大小的功能:                    1)初始化画笔. 2)设置画笔的大小为所选择的大小. 3)用一个变量记住当前画笔的大小,用于在进行其他操作后还保持之前设置的画笔大小. 2. 设置画笔颜色的功能:     

开启phpMyAdmin高级功能的设置方法

注:本文基于phpMyAdmin5.5,使用LNMP环境 问题: 登录到phpMyAdmin以后,在主界面的底部,我们发现两条提示信息: 一条提示信息是"phpMyAdmin高级功能尚未完全设置,部分功能未激活.请点击这里查看原因",另外一条信息是"配置文件现在需要一个短语密码." 一旦出现这两条信息,就意味着phpMyAdmin中的部分功能不能使用.解决这个问题的操作步骤分为三部分:上传create_tables.sql文件.配置config.inc.php文件和

virtualbox安装增强功能并设置共享文件夹

我们在安装之前,必须得先安装好它所需要的依赖包,不然安装过程必定会出现错误! 一.安装依赖包 #yum install kernel-headers#yum install kernel-devel#yum install gcc* #yum install make 二.安装增强功能包1.安装命令 #mount /dev/cdrom /mnt/cdrom#cd /mnt/cdrom#./VBoxLinuxAdditions.run这里安装的时候可能要等上一会,大家耐心点哦!安装完成后,一般都要

关于xml中自动提示功能的设置

我们在编写xml文件时如果有自动提示功能,将会事半功倍,下面我就怎么设置xml进行说明: 在xml文件的开始几行一般有编写xml文件的语法要求;如 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

vsftpd使用虚拟账号功能以及设置相关权限

我们登录FTP有三种方式,匿名登录.本地用户登录和虚拟用户登录. 匿名登录:在登录FTP时使用默认的用户名,一般是ftp或anonymous. 本地用户登录:使用系统用户登录,在/etc/passwd中. 虚拟用户登录:这是FTP专有用户,有两种方式实现虚拟用户,本地数据文件和数据库服务器. FTP虚拟用户是FTP服务器的专有用户,使用虚拟用户登录FTP,只能访问FTP服务器提供的资源,大大增强了系统的安全. 例:FTP虚拟账号 公司为了宣传最新的产品信息,计划搭建FTP服务器,为客户提供相关的