zoukankan      html  css  js  c++  java
  • Android:Volley的使用及其工具类的封装

    Android:Volley的使用及其工具类的封装

    一. Volley简介

    Volley的中文翻译为“齐射、并发”,是在2013年的Google大会上发布的一款Android平台网络通信库,具有网络请求的处理、小图片的异步加载和缓存等功能,能够帮助 Android APP 更方便地执行网络操作,而且更快速高效。

    在Google IO的演讲上,其配图是一幅发射火弓箭的图,有点类似流星。这表示,Volley特别适合数据量不大但是通信频繁的场景。见下图:

    此处输入图片的描述

    Volley 有如下的优点:

    • 自动调度网络请求;
    • 高并发网络连接;
    • 通过标准的 HTTP cache coherence(高速缓存一致性)缓存磁盘和内存透明的响应;
    • 支持指定请求的优先级;
    • 网络请求cancel机制。我们可以取消单个请求,或者指定取消请求队列中的一个区域;
    • 框架容易被定制,例如,定制重试或者回退功能;
    • 包含了调试与追踪工具;

    Volley 不适合用来下载大的数据文件。因为 Volley 会保持在解析的过程中所有的响应。对于下载大量的数据操作,请考虑使用 DownloadManager。

    在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如:android-async-http、retrofit、okhttp等。他们各有优劣,可有所斟酌地选择选择更适合项目的类库。

    附录:

    Volley的github地址:https://github.com/mcxiaoke/android-volley

    Google I/O 2013 – Volley: Easy, Fast Networking for Android:https://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded

    二. Volley jar包的导入

    Volley 框架的核心代码是托管在 AOSP 仓库的 frameworks/volley 中,相关的工具放在 toolbox 下。

    把 Volley 添加到项目中最简便的方法是 Clone 仓库,然后把它设置为一个 library project。

    1) clone代码:

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

    2)将代码编译成jar包:

    android update project -p . ant jar
    

    如无意外,将获得volley.jar包。

    3)添加volley.jar到你的项目中:

    可参考:http://jingyan.baidu.com/article/e6c8503c7190b7e54f1a1893.html

    备注:

    附上我的volley.jar包的地址:http://pan.baidu.com/s/1sjSwCrV,方便大家直接下载使用。当然,Volley更新较快,还是希望大家能直接通过clone代码后进行编译。

    三. Volley框架的详细使用:

    Volley工作原理图如下:

    图片转载自`https://bxbxbai.github.io/2014/09/14/android-working-with-volley/`

    使用Volley框架实现网络数据请求主要有以下三个步骤:

    • 1.创建RequestQueue对象,定义网络请求队列;
    • 2.创建XXXRequest对象(XXX代表String,JSON,Image等等),定义网络数据请求的详细过程;
    • 3.把XXXRequest对象添加到RequestQueue中,开始执行网络请求。

    3.1 创建RequestQueue对象

    一般而言,网络请求队列都是整个APP内使用的全局性对象,因此最好写入Application类中:

    public class MyApplication extends Application{
        // 建立请求队列
        public static RequestQueue queue;
    
        @Override
        public void onCreate() {
            super.onCreate();
            queue = Volley.newRequestQueue(getApplicationContext());
        }
    
        public static RequestQueue getHttpQueue() {
            return queue;
        }
    }
    

    这是,我们还需要修改AndroidManifest.xml文件,使APP的Application对象为我们刚定义的MyApplication,并添加INTERNET权限:

    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
    </application>
    

    3.2 创建XXXRequest对象并添加到请求队列中

    Volley提供了JsonObjectRequest、JsonArrayRequest、StringRequest等Request形式:

    • JsonObjectRequest:返回JSONObject对象;
    • JsonArrayRequest:返回JsonArray对象;
    • StringRequest:返回String。

    另外可以继承Request自定义Request。

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // GET请求
            VolleyGet();
    
            // POST请求
            VolleyPost();
        }
    
        // 定义POST请求的方法
        private void VolleyPost() {
            // 请求地址
            String url = "http://ce.sysu.edu.cn/hope/";
    
            // 创建StringRequest,定义字符串请求的请求方式为POST,
            StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
                // 请求成功后执行的函数
                @Override
                public void onResponse(String s) {
                    // 打印出POST请求返回的字符串
                    Toast.makeText(MainActivity.this, "POST: " + s, Toast.LENGTH_LONG).show();
                }
            }, new Response.ErrorListener() {
                // 请求失败时执行的函数
                @Override
                public void onErrorResponse(VolleyError volleyError) {
    
                }
            }){
    
                // 定义请求数据
                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
                    Map<String, String> hashMap = new HashMap<String, String>();
                    hashMap.put("phone", "11111");
                    return hashMap;
                }
            };
            // 设置该请求的标签
            request.setTag("abcPost");
    
            // 将请求添加到队列中
            MyApplication.getHttpQueue().add(request);
        }
    
        // 定义GET请求的方法
        private void VolleyGet() {
            // 定义请求地址
            String url = "http://ce.sysu.edu.cn/hope/";
            StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
                @Override
                public void onResponse(String s) {
                    // 打印出GET请求返回的字符串
                    Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
    
                }
            });
    
            // 设置该请求的标签
            request.setTag("abcGet");
    
            // 将请求添加到队列中
            MyApplication.getHttpQueue().add(request);
        }
    }
    

    输出:

    // POST请求
    POST: <厚朴网站首页源代码。。。>
    // GET请求
    GET: <厚朴网站首页源代码。。。>
    

    3.3 关闭请求

    3.3.1 关闭特定标签的网络请求:

    // 网络请求标签为"abcGet"
    public void onStop() {
        super.onStop();
        MyApplication.getHttpQueues.cancelAll("abcGet");
    }
    

    3.3.2 取消这个队列里的所有请求:

    在activity的onStop()方法里面,取消所有的包含这个tag的请求任务。

    @Override  
    protected void onStop() {  
        super.onStop();  
        mRequestQueue.cancelAll(this);  
    }
    

    四. GET和POST请求工具库的封装

    4.1 重写Application

    因为网络请求队列相对于APP应用老说是全局对象,因此可以定义在全局中。为此,我们新建一个LIMSApplication,并让其继承自Application。

    LIMSApplication.java文件:

    public class LIMSApplication extends Application {
        public static RequestQueue volleyQueue;
        @Override
        public void onCreate() {
            super.onCreate();
    
            /* Volley配置 */
            // 建立Volley的Http请求队列
            volleyQueue = Volley.newRequestQueue(getApplicationContext());
        }
    
        // 开放Volley的HTTP请求队列接口
        public static RequestQueue getRequestQueue() {
            return volleyQueue;
        }
    }
    

    不要忘记在AndroidManifest.xml文件中修改Application的name和相应的网络请求权限:

    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:name=".LIMSApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
    </application>
    

    4.2 GET和POST请求的封装:

    目前,VolleyRequestUtil工具库只包含了两个函数,分别获取GET和POST请求。

    VolleyRequestUtil.java:

    public class VolleyRequestUtil {
    
        public static StringRequest stringRequest;
        public static Context context;
    
        /*
        * 获取GET请求内容
        * 参数:
        * context:当前上下文;
        * url:请求的url地址;
        * tag:当前请求的标签;
        * volleyListenerInterface:VolleyListenerInterface接口;
        * */
        public static void RequestGet(Context context, String url, String tag, VolleyListenerInterface volleyListenerInterface) {
            // 清除请求队列中的tag标记请求
            LIMSApplication.getRequestQueue().cancelAll(tag);
            // 创建当前的请求,获取字符串内容
            stringRequest = new StringRequest(Request.Method.GET, url, volleyListenerInterface.responseListener(), volleyListenerInterface.errorListener());
            // 为当前请求添加标记
            stringRequest.setTag(tag);
            // 将当前请求添加到请求队列中
            LIMSApplication.getRequestQueue().add(stringRequest);
            // 重启当前请求队列
            LIMSApplication.getRequestQueue().start();
        }
    
        /*
        * 获取POST请求内容(请求的代码为Map)
        * 参数:
        * context:当前上下文;
        * url:请求的url地址;
        * tag:当前请求的标签;
        * params:POST请求内容;
        * volleyListenerInterface:VolleyListenerInterface接口;
        * */
        public static void RequestPost(Context context, String url, String tag, final Map<String, String> params, VolleyListenerInterface volleyListenerInterface) {
            // 清除请求队列中的tag标记请求
            LIMSApplication.getRequestQueue().cancelAll(tag);
            // 创建当前的POST请求,并将请求内容写入Map中
            stringRequest = new StringRequest(Request.Method.POST, url, volleyListenerInterface.responseListener(), volleyListenerInterface.errorListener()){
                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
                    return params;
                }
            };
            // 为当前请求添加标记
            stringRequest.setTag(tag);
            // 将当前请求添加到请求队列中
            LIMSApplication.getRequestQueue().add(stringRequest);
            // 重启当前请求队列
            LIMSApplication.getRequestQueue().start();
        }
    }
    

    4.3 Volley请求(成功或失败)的监听事件封装:

    封装Volley请求(成功或失败)的监听事件,见VolleyListenerInterface.java:

    public abstract class VolleyListenerInterface {
        public Context mContext;
        public static Response.Listener<String> mListener;
        public static Response.ErrorListener mErrorListener;
    
        public VolleyListenerInterface(Context context, Response.Listener<String> listener, Response.ErrorListener errorListener) {
            this.mContext = context;
            this.mErrorListener = errorListener;
            this.mListener = listener;
        }
    
        // 请求成功时的回调函数
        public abstract void onMySuccess(String result);
    
        // 请求失败时的回调函数
        public abstract void onMyError(VolleyError error);
    
        // 创建请求的事件监听
        public Response.Listener<String> responseListener() {
            mListener = new Response.Listener<String>() {
                @Override
                public void onResponse(String s) {
                    onMySuccess(s);
                }
            };
            return mListener;
        }
    
        // 创建请求失败的事件监听
        public Response.ErrorListener errorListener() {
            mErrorListener = new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    onMyError(volleyError);
                }
            };
            return mErrorListener;
        }
    }
    

    4.3 Volley图片加载库的封装:

    Volley库还具有图片加载的功能。但适合小图片的异步加载,不适合于比较大的图片资源的请求。

    Volley提供了多种Request方法,譬如ImageRequest、ImageLoader、NetWorkImageView。

    网络图片资源的请求封装如下:

    ImageLoaderUtil.java:

    public class ImageLoaderUtil {
    
        /*
        * 通过ImageRequest来显示网络图片
        * */
        public static void setImageRequest(String url, final ImageView imageView) {
            ImageRequest imageRequest = new ImageRequest(url, new Response.Listener<Bitmap>() {
                @Override
                public void onResponse(Bitmap bitmap) {
                    imageView.setImageBitmap(bitmap);
                }
            }, 0, 0, Bitmap.Config.RGB_565, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    imageView.setBackgroundResource(R.mipmap.ic_launcher);
                }
            });
            LIMSApplication.getRequestQueue().add(imageRequest);
        }
    
        /*
        * 通过ImageLoader来显示网络图片
        * */
        public static void setImageLoader(String url, ImageView imageView, int defaultImageResId, int errorImageResId) {
            ImageLoader loader = new ImageLoader(LIMSApplication.getRequestQueue(), new BitmapCache());
            ImageLoader.ImageListener imageListener = ImageLoader.getImageListener(imageView, defaultImageResId, errorImageResId);
            loader.get(url, imageListener);
        }
    
        /*
        * 通过Volley的NetWorkImageView来显示网络图片
        * */
        public static void setNetWorkImageView(String url, NetworkImageView netWorkImageView, int defaultImageResId, int errorImageResId) {
            ImageLoader loader = new ImageLoader(LIMSApplication.getRequestQueue(), new BitmapCache());
    
            netWorkImageView.setDefaultImageResId(defaultImageResId);
            netWorkImageView.setErrorImageResId(errorImageResId);
            netWorkImageView.setImageUrl(url, loader);
        }
    }
    

    五. VolleyRequestUtil与ImageLoaderUtil的使用

    5.1 用GET方式请求网络资源:

    new VolleyRequestUtil().RequestGet(this, "http://ce.sysu.edu.cn/hope/", "hopePage", 
        new VolleyListenerInterface(this, VolleyListenerInterface.mListener, VolleyListenerInterface.mErrorListener) {
        // Volley请求成功时调用的函数
        @Override
        public void onMySuccess(String result) {
            Toast.makeText(this, s, Toast.LENGTH_LONG).show();
        }
    
        // Volley请求失败时调用的函数
        @Override
        public void onMyError(VolleyError error) {
            // ...
        }
    });
    

    输出:厚朴网站首页的源代码。

    5.2 用POST方式请求网络资源:

    new VolleyRequestUtil().RequestPOST(this, "http://ce.sysu.edu.cn/hope/", "hopePage", 
        new VolleyListenerInterface(this, VolleyListenerInterface.mListener, VolleyListenerInterface.mErrorListener) {
        // Volley请求成功时调用的函数
        @Override
        public void onMySuccess(String result) {
            Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
        }
    
        // Volley请求失败时调用的函数
        @Override
        public void onMyError(VolleyError error) {
            // ...
        }
    });
    

    输出:厚朴网站首页的源代码。

    5.3 通过ImageRequest来显示网络图片:

    // 参数分别为:请求图片的地址、图片的容器ImageView
    ImageView imgView = (ImageView) findViewById(R.id.imgView);
            new ImageLoaderUtil().setImageRequest("http://7xinb0.com1.z0.glb.clouddn.com/skin/HopeRebuild/dist/images/logo/logo_40.png", imgView);
    

    在布局文件中,定义ImageView:

    <ImageView
            android:id="@+id/imgView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    

    5.4 通过ImageLoader来显示网络图片:

    // 参数分别为:请求图片的地址、图片的容器ImageView、默认显示的图片ResourceID、请求失败时显示的图片的ResourceID
    new ImageLoaderUtil().setImageLoader("http://7xinb0.com1.z0.glb.clouddn.com/skin/HopeRebuild/dist/images/logo/logo_40.png", imgView, R.mipmap.default, R.mipmap.error);
    

    在布局文件中,定义ImageView:

    <ImageView
            android:id="@+id/imgView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    

    5.5 通过Volley的NetWorkImageView来显示网络图片:

    // 参数分别为:请求图片的地址、图片的容器NetworkImageView、默认显示的图片ResourceID、请求失败时显示的图片的ResourceID
    NetworkImageView netWorkImageView = (NetworkImageView) findViewById(R.id.imgNetworkView);
            new ImageLoaderUtil().setNetWorkImageView("http://7xinb0.com1.z0.glb.clouddn.com/skin/HopeRebuild/dist/images/logo/logo_40.png", netWorkImageView, R.mipmap.default, R.mipmap.error);
    

    在布局文件中,定义NetworkImageView:

    <com.android.volley.toolbox.NetworkImageView  
                   android:id="@+id/imgNetworkView"  
                   android:layout_width="300dp"  
                   android:layout_height="300dp"  
                   android:layout_centerHorizontal="true"/>
    

    六. 后记

    该Volley的封装中,暂未考虑到图片和数据缓存。

    有一些地方封装得仍不够抽象,有待完善。

    非常欢迎读者能提出修改建议,一起进步。

    本文作者:凳子_Joinery,转载请注明出处:http://www.dengzhr.com/others/mobile/android/762

  • 相关阅读:
    在iOS 11上出现libsystem_kernel.dylib`__abort_with_payload崩溃问题的解决
    Mac上安装软件出现“XXXX”已损坏,打不开,你应该将它移到废纸篓 的问题解决
    iOS10.3系统以后(NSStrikethroughStyleAttributeName)富文本删除线失效不显示的坑
    Mac终端操作命令
    解决设置selectedBackgroundView后会把cell上带背景颜色的控件遮住的问题
    iOS开发字体大全
    UITapGestureRecognizer的用法
    UIButton设置图片和标题上下垂直分布的总结
    Xcode8.3.2制作静态库
    多线程
  • 原文地址:https://www.cnblogs.com/jidan/p/5101351.html
Copyright © 2011-2022 走看看