Volley的使用以及介绍

1、简单介绍

因为说了是简单介绍,这里就不做复杂说明。

Volley是google方法出品的网络框架,在Goolge IO 2013大会上发布,目前在Android develop Training可以看到介绍,Training介绍原文地址,这个地址是需要翻墙的。

在附上介绍视频地址,同样也是需要翻墙的。Volley: Easy, Fast Networking for Android

虽然现在大家项目中可能都使用的是 Retrofit,但是学习一下Volley还是很有必要的,总的来说是Android的google爸爸出品的,而且就目前状态来看,代码仍然在维护中。

在这里插入图片描述

2、Transmitting Network Data Using Volley(使用Volley进行网络数据传输)

Volley是一个HTTP库,它使Android应用程序的网络更容易,最重要的是更快。

Volley可以在Github上找到代码

Volley具有以下特点:

  • 1、自动调度网络请求
  • 2、支持多个并发网络连接
  • 3、具有标准的HTTP缓存一致性的硬盘和内存缓存
  • 4、支持请求优先级
  • 5、支持请求取消API,可以取消单个请求,也支持设置要取消的请求的块或范围
  • 6、更加容易自行定制
  • 7、强健的顺序性可以保证异步获取的数据正确的填充你的UI
  • 8、Debugging and tracing tools.

Volley擅长用于填充UI的RPC-TYPE操作,如将搜索结果页作为结构化数据抓取。它易于与任何协议集成,并为输出原始字符串、images和JSON提供了内建的支持。可以让你更加专注于具体的业务逻辑功能。

Volley不适合大型下载或者流媒体操作,因为为了方便解析Volley在内存中持有了所有的Response信息。对于大型下载可以考虑使用其他方式,比如DownloadManager。

如果想在你的项目中集成Volley,可以加入如下的代码

dependencies {
    ...
    compile 'com.android.volley:volley:1.0.0'
}

当然你也可以clone下来代码,以module的形式加入到项目中

git clone https://github.com/google/volley

2、Sending a Simple Request(发送一个简单的请求)

2-1、添加INTERNET权限
 <uses-permission android:name="android.permission.INTERNET" />
2-2、使用RequestQueue

Volley提供了一个方便的方法Volley.newRequestQueue去配置RequestQueue,当然是用的默认值去开启队列。下面是使用例子。

final TextView mTextView = (TextView) findViewById(R.id.text);
...

// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.google.com";

// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        // Display the first 500 characters of the response string.
        mTextView.setText("Response is: "+ response.substring(0,500));
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        mTextView.setText("That didn't work!");
    }
});
// Add the request to the RequestQueue.
queue.add(stringRequest);

Volley总是将解析的返回结果呈现在主线程中,这样方便了去做UI相关的填充处理操作,你可以方便的拿到数据去直接修改ui控件。它还提供了很多有用的功能,比如取消一个请求。

2-3、发送请求

发送一个请求,你只需要构造一个请求,并把它通过RequestQueue#add()方法添加到RequestQueue中去,在添加了请求之后,它将通过管道(pipeline)移动,得到服务,并对其原始相应进行解析和分发。

当你调用add()方法,Volley将运行一个缓存处理线程和一个网络调度线程池。当你添加一个请求到队列中,它将被缓存线程进行一个判断,如果请求对应的缓存服务可以工作,也就是说请求的缓存存在并且没有过期,缓存线程会进行解析并且分发返回结果到主线程(UI线程)。如果不能从缓存中获取(这里也包括缓存过期的情况),那么它就被放置在消息队列中。有一个网络任务线程去处理请求,执行HTTP事务,解析工作线程上的返回结果,将返回结果写入缓存,并将解析后的结果返回分发到主线程中。

note:诸如阻塞IO,解析数据等这种耗时操作都是在工作线程中完成的,你可以从任何线程添加一个请求,但是响应总是要在主线程。

image

2-4、取消请求

取消一个请求,在你的Request对象调用cancel()。一旦取消,Volley保证你的响应结果处理分发将永远不同被调用(个人理解是不管你网络请求处理结果如何,一旦取消,负责结果分发的处理就中断了)。这就意味着你可以在onStop中取消你的没有执行的请求,而且你完全不用去在你的请求结果处理返回部分检查getActivity() == null(反正这块处理逻辑都不会走了)。

要使用这种行为,你应该追踪你所有的飞行请求(in-flight: 应该理解为所有的已经请求,但是还没有拿到请求结果的请求),以便在合适的时机取消它们。这里有一个简单方法:你可以用一个标记(tag)和请求关联起来,然后你可以用这个标记来提供取消的范围。

Here is an example that uses a string value for the tag:

  • 1、Define your tag and add it to your requests.
public static final String TAG = "MyTag";
StringRequest stringRequest; // Assume this exists.
RequestQueue mRequestQueue;  // Assume this exists.

// Set the tag on the request.
stringRequest.setTag(TAG);

// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
  • 2、In your activity’s onStop() method, cancel all requests that have this tag.
@Override
protected void onStop () {
    super.onStop();
    if (mRequestQueue != null) {
        mRequestQueue.cancelAll(TAG);
    }
}

取消请求时要注意,如果你的请求结果需要推进一个状态或者另一个进程,你应该了解到,这个对应的处理(状态或者另一个进程相关操作)同样不会被调用到。

3、Setting Up a RequestQueue(配置RequestQueue)

3-1、设置网络和缓存

一个RequestQueue会做两个工作:传输网络请求和处理数据缓存。在Volley的自带工具箱(toolbox)中提供了默认实现:

DiskBaseCache提供一个与内存中索引一一对应的文件。BasicNetwork提供一个基于HTTP的网络传输协议客户端。

BasicNetwork是Volley的默认网络实现,一个网络必须与您的应用程序使用HTTP客户端初始化链接网络,通常是HttpUrlConnection

下面代码片段展示如何设置RequestQueue

RequestQueue mRequestQueue;

// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap

// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());

// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);

// Start the queue
mRequestQueue.start();

String url ="http://www.example.com";

// Formulate the request and handle the response.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
        new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        // Do something with the response
    }
},
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // Handle error
    }
});

// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);

// ...

如果你只想要做一次请求,不需要线程池,你可以创建一个RequestQueue在你任何需要的地方,在数据返回之后,调用stop()即可。更常用的方法是直接使用Volley.newRequestQueue()去执行一个简单的请求,并且保持RequestQueue在你的应用程序中单例存在。

3-2、使用单例模式

为了使整个应用的生命周期中,你的网络请求都可用,可以将RequestQueue设置为单例模式。

一个需要注意的点是,RequestQueue必须使用Application Context进行初始化,而不是Activity Context,这将确保了RequestQueue在整个应用的生命周期有效。

public class MySingleton {
    private static MySingleton mInstance;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private static Context mCtx;

    private MySingleton(Context context) {
        mCtx = context;
        mRequestQueue = getRequestQueue();

        mImageLoader = new ImageLoader(mRequestQueue,
                new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap>
                    cache = new LruCache<String, Bitmap>(20);

            @Override
            public Bitmap getBitmap(String url) {
                return cache.get(url);
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                cache.put(url, bitmap);
            }
        });
    }

    public static synchronized MySingleton getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new MySingleton(context);
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            // getApplicationContext() is key, it keeps you from leaking the
            // Activity or BroadcastReceiver if someone passes one in.
            mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
        }
        return mRequestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }

    public ImageLoader getImageLoader() {
        return mImageLoader;
    }
}

下面是一个使用实例:

// Get a RequestQueue
RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()).
    getRequestQueue();

// ...

// Add a request (in this example, called stringRequest) to your RequestQueue.
MySingleton.getInstance(this).addToRequestQueue(stringRequest);

4、Making a Standard Request(发起一个标准请求)

Volley内建支持了如下请求类型:

StringRequest: 指定一个url,请求返回字符串类型的结果。

JsonObjectRequestJsonArrayRequest,指定一个url,返回结果是JSON格式或者JSONAarray格式。

下面的例子,使用JsonObjectRequest展示:

TextView mTxtDisplay;
ImageView mImageView;
mTxtDisplay = (TextView) findViewById(R.id.txtDisplay);
String url = "http://my-json-feed";

JsonObjectRequest jsObjRequest = new JsonObjectRequest
        (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

    @Override
    public void onResponse(JSONObject response) {
        mTxtDisplay.setText("Response: " + response.toString());
    }
}, new Response.ErrorListener() {

    @Override
    public void onErrorResponse(VolleyError error) {
        // TODO Auto-generated method stub

    }
});

// Access the RequestQueue through your singleton class.
MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);

5、Implementing a Custom Request(自定义实现一个请求)

Volley的工具箱中提供了网络请求,缓存的默认实现,以及几种请求方式,如果这些都不满足你的实际使用的话,Volley也支持自定义实现。

5-1、自定义网络请求

想要自己实现网络请求,需要如下几步:

  • 1、继承Request<T>,这里的泛型T就是处理之后的返回结果类型,如果你期待的解析之后类型是String,可能你需要写成Request,具体的实现可以在Volley Toolbox中找到。
  • 2、实现抽象方法parseNetworkResponse()deliverResponse

parseNetworkResponse
这个方法主要是对于返回的结果集进行解析处理。

@Override
protected Response<T> parseNetworkResponse(
        NetworkResponse response) {
    try {
        String json = new String(response.data,
        HttpHeaderParser.parseCharset(response.headers));
    return Response.success(gson.fromJson(json, clazz),
    HttpHeaderParser.parseCacheHeaders(response));
    }
    // handle errors
...
}

parseNetworkResponse的参数NetworkResponse里面包含了HTTP状态码,header信息等内容。

deliverResponse

protected void deliverResponse(T response) {
        listener.onResponse(response);
5-2、Example: GsonRequest
public class GsonRequest<T> extends Request<T> {
    private final Gson gson = new Gson();
    private final Class<T> clazz;
    private final Map<String, String> headers;
    private final Listener<T> listener;

    /**
     * Make a GET request and return a parsed object from JSON.
     *
     * @param url URL of the request to make
     * @param clazz Relevant class object, for Gson's reflection
     * @param headers Map of request headers
     */
    public GsonRequest(String url, Class<T> clazz, Map<String, String> headers,
            Listener<T> listener, ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.clazz = clazz;
        this.headers = headers;
        this.listener = listener;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        return headers != null ? headers : super.getHeaders();
    }

    @Override
    protected void deliverResponse(T response) {
        listener.onResponse(response);
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        try {
            String json = new String(
                    response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(
                    gson.fromJson(json, clazz),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JsonSyntaxException e) {
            return Response.error(new ParseError(e));
        }
    }
}

6、实例代码

https://github.com/fireking0415/VolleySample

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值