Volley使用介绍

QuibblerQuibbler 2021-02-02 约 21 分钟 1797 次阅读

Volley使用介绍

安卓开发要对几个网络开源库非常熟悉:OkHttp、Volley、Retrofit。先从轻量级的网络请求库Volley学习,它的源码不到1万行,麻雀虽小五脏俱全。

1、Volley介绍

Volley是Google官方2013年发布的Android平台的网络通信库。该开源框架目前看来已经非常稳定,大部分代码提交记录定格在3年前(不是没人维护了,而是不需要再修改)。

GitHub:google/volley

1.1、特点

可以访问普通的网络数据、或者Json数据、再或者下载图片。这写都是Android开发中最常见的网络请求场景,使用Volley可以提高项目的开发效率,降低重复工作,这么好的轮子不用?

此外,Volley还可以对请求队列进行排序,取消,缓存等。

1.2、适用场景

Volley适合进行数据量不大但是通信频繁的网络操作,比如评论、点赞等场景。

但对于数据量比较大的网络操作其性能表现就比较差,不宜用Volley下载文件操作、短视频缓存。此时应该选用其它合适的网络库或者开发者用原生的HttpURLConnection实现。

2、引入Volley

在项目的build.gradle中添加下面Volley依赖,最新稳定版本是1.1.1,很久没有更新了。参考 文档 > 指南 > Volley 概览">Android 开发者 > 文档 > 指南 > Volley 概览

dependencies {
        ...
        implementation 'com.android.volley:volley:1.1.1'
    }

使用Volley别忘了在AndroidManifest.xml中添加android.permission.INTERNET网络权限

<!--网络权限-->
    <uses-permission android:name="android.permission.INTERNET" />

3、请求回调Listener

每个请求都需要一个结果返回监听器Listener<T>和者错误监听器ErrorListener,它们都是定义在Response<T>中的接口。在请求返回后在主线程中回调Listener<T>的onResponse(T response)方法,当请求失败出错,则回调ErrorListener的onErrorResponse(VolleyError error)方法。

/** Callback interface for delivering parsed responses. */
    public interface Listener<T> {
        /** Called when a response is received. */
        void onResponse(T response);
    }
    
    /** Callback interface for delivering error responses. */
    public interface ErrorListener {
        /**
         * Callback method that an error has been occurred with the provided error code and optional
         * user-readable message.
         */
        void onErrorResponse(VolleyError error);
    }

4、请求示例

Volley将网络请求抽象为Request<T>,内部有三个实现类:StringRequest、JsonRequest、ImageRequest。用Kotlin分别简单演示一下Volley请求网络数据、Json数据、加载图片。参考 文档 > 指南 > 提出标准请求">Android 开发者 > 文档 > 指南 > 提出标准请求。

源码流程以后再研究。

4.1、StringRequest

先构造一个StringRequest文本请求,有两个构造函数:

public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) {
        super(method, url, errorListener);
        mListener = listener;
    }
    
    public StringRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
        this(Request.Method.GET, url, listener, errorListener);
    }

构造好StringRequest之后将其添加到Volley请求队列中。

private fun stringRequest() {
        val url: String = "https://www.baidu.com"
        
        val stringRequest: StringRequest = StringRequest(Request.Method.GET, url,
                {
                    //callback in main thread
                    textView.text = it.toString()
                    Log.d(TAG, it.toString())
                },
                {
                    Log.e(TAG, it.message.toString())
                })
                
        Volley.newRequestQueue(this).add(stringRequest)
    }

4.2、JsonRequest(JsonObjectRequest 和 JsonArrayRequest)

JsonRequest已经被废弃,取而代之的是两个子类JsonObjectRequest和JsonArrayRequest。分别用来解析Json对象和Json数组。

JsonArrayRequest的构造方法参数如下

public JsonArrayRequest(String url, Listener<JSONArray> listener, ErrorListener errorListener) {
        super(Method.GET, url, null, listener, errorListener);
    }
    
    public JsonArrayRequest(int method, String url, JSONArray jsonRequest,
                            Listener<JSONArray> listener, ErrorListener errorListener) {
        super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, errorListener);
    }

JsonObjectRequest的构造方法参数如下

public JsonObjectRequest(int method, String url, JSONObject jsonRequest,
                             Listener<JSONObject> listener, ErrorListener errorListener) {
        super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, errorListener);
    }
    
    public JsonObjectRequest(String url, JSONObject jsonRequest,
                             Listener<JSONObject> listener, ErrorListener errorListener) {
        this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest, listener, errorListener);
    }

构造好JsonRequest之后将其添加到Volley请求队列中。

private fun jsonRequest() {
        val url: String = "http://quibbler.cn:3000/search?keywords=海阔天空"
        
        val jsonRequest: JsonObjectRequest = JsonObjectRequest(Request.Method.GET,
                url,
                null,
                {
                    //JSONObject
                    textView.text = it.toString()
                },
                {
                    Log.d(TAG, it?.message.toString())
                })
                
        VolleyInstance.addToRequestQueue(jsonRequest)
    }

4.3、ImageRequest

构造ImageRequest的参数比较多,也是合情合理,熟悉网络图片加载的开发应该对这些参数比较熟悉。关于Bitmap见Bitmap位图介绍。

/**
     * @param url           图片地址
     * @param listener      请求响应成功回调
     * @param maxWidth      图片最大宽度
     * @param maxHeight     图片最大高度
     * @param scaleType     ImageViews ScaleType用于计算所需的图像大小。
     * @param decodeConfig  图片的颜色属性,其值是Bitmap.Config类的几个常量
     * @param errorListener 请求响应失败回调
     */
    public ImageRequest(String url, Response.Listener<Bitmap> listener, int maxWidth, int maxHeight,
                        ImageView.ScaleType scaleType, Bitmap.Config decodeConfig, Response.ErrorListener errorListener) {
        super(Request.Method.GET, url, errorListener);
        ...
    }

构造好ImageRequest之后将其添加到Volley请求队列中加载图片,网络图片加载完成回调中可以直接设置给ImageView控件。

private fun imageRequest() {
        val url: String = "http://quibbler.cn/upload/forum/10.png"
        
        val imageRequest: ImageRequest = ImageRequest(url,
                {
                    //Bitmap
                    imageView.setImageBitmap(it)
                },
                200, 200,
                ImageView.ScaleType.FIT_CENTER,
                Bitmap.Config.ALPHA_8,
                {
                    Log.d(TAG, it?.message.toString())
                })
        imageRequest.setShouldCache(true).setTag(TAG)
        
        VolleyInstance.addToRequestQueue(imageRequest)
    }

5、最佳单例Volley

得益于Kotlin的语法层面支持,可以完美的实现一个Volley单例,整个应用全局可以获取RequestQueue进行请求,这样的单例是最高效的。而且应该通过全局Application Context初始化,而不是Activity的Context,获取应用全局Context方法见如何获取全局Context?。参考 文档 > 指南 > 使用单例模式">Android 开发者 > 文档 > 指南 > 使用单例模式。

import android.graphics.Bitmap
    import android.util.LruCache
    import com.android.volley.Request
    import com.android.volley.RequestQueue
    import com.android.volley.toolbox.ImageLoader
    import com.android.volley.toolbox.Volley
    
    object VolleyInstance {
    
        private val requestQueue: RequestQueue = Volley.newRequestQueue(MyApplication.getApplication())
        
        private val imageLoader: ImageLoader = ImageLoader(requestQueue,
                object : ImageLoader.ImageCache {
                    val cache = LruCache<String, Bitmap>(20)
                    override fun getBitmap(url: String): Bitmap {
                        return cache.get(url)
                    }
                    override fun putBitmap(url: String, bitmap: Bitmap) {
                        cache.put(url, bitmap)
                    }
                }
        )
        
        fun <T> addToRequestQueue(request: Request<T>) {
            requestQueue.add(request)
        }
        
        fun cancelRequest(tag: String?) {
            requestQueue.cancelAll(tag)
        }
        
        fun getRequestQueue(): RequestQueue {
            return requestQueue
        }
        
        fun getImageLoader(): ImageLoader {
            return imageLoader
        }
        
    }

使用Java开发的项目单例模式详见单例的五种方式。

参考资料:

        google/volley

         文档 > 指南 > Volley 概览">Android 开发者 > 文档 > 指南 > Volley 概览

         文档 > 指南 > 发送简单请求">Android 开发者 > 文档 > 指南 > 发送简单请求

         文档 > 指南 > 设置 RequestQueue">Android 开发者 > 文档 > 指南 > 设置 RequestQueue

         文档 > 指南 > 提出标准请求">Android 开发者 > 文档 > 指南 > 提出标准请求

         文档 > 指南 > 实现自定义请求">Android 开发者 > 文档 > 指南 > 实现自定义请求

        

相关推荐

精选
Airbnb开源项目
开源

Airbnb开源项目

Airbnb Engineering & Data ScienceAirflow Use Apache Airflow (incubating) to author workflows as directed acyclic graphs (DAGs) of tasks12,263Airpal Web UI for PrestoDB2,502Aerosolve A machine learning

1.8k
OkHttp线程池和连接池
开源

OkHttp线程池和连接池

OkHttp线程池和连接池了解了OkHttp的网络请求流程以及拦截器实现原理,再关注OkHttp中两个重要的:OkHttp的线程池和连接池。1、OkHttp线程池在OkHttp网络请求流程一文中,我们分析了OkHttp异步和同步请求流程。请求最后都在Dispatcher中分发调度处理,最后被ExecutorService执行。1.1、DispatcherDispatcher中执行任务的执行器是ex

5.2k
优美的开源动效库:Lottie
开源

优美的开源动效库:Lottie

优美的开源动效库:Lottie1、强大的动效LottieLottie是一个适用于Android,iOS,Web和Windows的库,它可以使用Bodymovin解析以json格式导出的Adobe After Effects动画,并在移动设备和Web上原生渲染它们!GitHub:https://github.com/airbnb/lottie-androidLottie官网:http://airbn

4.3k