Volley网络请求概述

    xiaoxiao2021-03-25  135

    特点:

    · 自动调度网络请求

    · 支持并发网络连接(即支持多线程)

    · 支持标准的HTTP缓存协议(由服务器来决定是否缓存数据)

    · 支持请求优先级设置(4级)

    · 支持取消单个或多个请求

    · 易于定制(重试),扩展性强。比如Retry&Backoff机制

    · 强大的网络请求能力让你轻松的发送异步请求来填充UI数据

    · 提供调试和跟踪工具

    优点:

    擅长将RPC(远程过程调用协议,C/S模式)类型的操作,用来展示服务器数据。比如以某种数据格式获取一页搜索结果。支持任意的数据传输格式,比如图片,字符串,json,你也可以定义自己的数据格式。其实就是自定义Request。Volley让你不再写这些重复的模板代码(网络请求逻辑,不再重复造轮子),这样你就可以专注于你应用本身的业务逻辑.

    缺点:

    由于Volley都是在内存中解析和处理数据,所以不适合大数据量的下载操作。如果需要下载大文件,可以考虑使用系统的DownloadManager。

     

    Volley使用

    1. 直接把代码clone下来,把volley的代码直接copy到你的project里,

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

    2. 作为一个library项目存在或者jar包存在

     

    3. 添加网络权限

    发送一个简单的请求

    步骤:

           1. 初始化一个RequestQueue

                mRequestQueue = Volley.newRequestQueue(this);

           2. 构建一个Request,这个Demo里我们使用的是StringRequest

                 StringRequest request = new StringRequest(

                        要访问的URL,

                        new Response.Listener<String>() {},//请求结果正确返回的listener

                        new Response.ErrorListener() {});    //请求结果错误返回的lisetner

           3. Request对象添加到RequestQueue

                mRequestQueue.add(request);

    Volley网络请求交互流程

    当调用add()方法的时候,Volley会运行一个缓存处理线程和一池子网络分发线程。

    当添加RequestRequestQueue的时候,请求先被缓存线程处理和鉴别:如果请求在缓存中有,则将缓存的response响应在缓存线程中进行解析并将解析后的响应分发给主线程。

    如果缓存中没有这个Request请求,则将这个Request放到网络队列中。第一个可用的网络线程将Request请求从队列中取出来,执行HTTP传输,并在工作线程中解析响应,将响应写进缓存,并将解析好的响应内容传给主线程进行分发。

    Volley将像IO、解析等耗时操作都放到了工作线程(子线程)来执行。你可以在任何线程去添加请求,Volley会将响应直接在主线程去进行分发。

     

    取消请求

    1)取消单个请求

    调用Request.cancel()方法。在onStop()方法中调用,因为一旦请求被取消volley会确保你的响应不会被执行,在onStop()方法中执行的话不需要判断getActivity()==null来判断掠过处理结果其他类似onSaveInstanceState()等保护性方法里面也不需要检测。

    2)取消多个请求

    requestQueue.cancelAll(this)

    为每个请求的对象都绑定一个tag对象,使用tag来提供取消的范围。所有请求都绑定到执行的Activity上(以Activitythis作为Requesttag),然后你可以在 onStop() 方法执行 requestQueue.cancelAll(this) 来取消这些请求。同样的,你可以为ViewPager中的所有请求图片的Request对象分别打上对应Tabtag。并在滑动时取消这些请求,用来确保新生成的tab不会被前面tab的请求任务阻塞。

    RequestQueue源码解析

    我们是通过Volley.newRequestQueue”方法来获取RequestQueue的实例的,Volley先构建了BasicNetworkDiskBasedCache,然后将这两个对象作为参数传递给了RequestQueue,构建出了RequestQueue对象。紧接着,调用了RequestQueue.start()方法,开启了消息队列。

    2.3之后HTTPURLConnection更适合安卓:因为它的API更简单,包更小,支持网络缓存,提高了速度节省电量。

    更易于定制:底层可以定制自己想要的方法实现网络请求。

    RequestQueue.start()”中,我们先在start之前进行了stop操作,然后先后构建了缓存线程CacheDispatcher和网络线程NetworkDispatcher,并将它们开启了。

    CacheDispatcherNetworkDispatcher是线程,是因为它们实际上都是Thread的子类,因此,调用CacheDispatcher或者NetworkDispatcher对象的start()方法,最终关键逻辑一定是走的是run()方法。

     

    CacheDispatcher源码解析

    1. CacheDispatcher被开启的时候,内部实际上是维护这一个while(true)死循环,不停的从队列中取Request

    2. 取到Request之后,判断Request的状态是否是被取消的状态,若被取消,则不做任何处理;

    3. Request没有被取消,则看是否有这个Request对应的缓存数据,若没有缓存数据,则将Request添加到网络队列中去;

    4. 有缓存数据,则判断缓存数据是否已经过期,若数据过期,则添加Request到网络队列;

    5. 若缓存数据没有过期,则将缓存的原始二进制数据解析成对应的Response数据,比如如果请求的是StringRequest就将二进制数据解析成String

    6. 将解析好的Response响应分发到主线程,将解析好的Response分发到主线程调用的是“mDelivery.postResponse(request, response);”,而这个mResponsePoster实际上是一个线程池,它重写了自己的execute方法,在execute方法执行时,将对应的Runnable对象借助Handler分发到了主线程去执行,因此,我们的Response响应最终会在主线程被调用方接收并进行处理。

    NetworkDispatcher源码解析

    1. NetworkDispatcher被开启的时候,内部实际上是维护这一个while(true)死循环,不停的从队列中取Request

    2. 取到Request之后,判断Request的状态是否是被取消的状态,若被取消,则不做任何处理;

    3. Request没有被取消,则根据Request去执行网络请求,获取响应Response

    4. 将响应的原始二进制数据解析成对应的Response数据,比如如果请求的是StringRequest就将二进制数据解析成String

    5. 缓存响应的数据Response

    6. 将响应的信息分发到主线程

    执行网络网络请求,获取Request对应的响应Response,调用的是“mNetwork.performRequest(request)”方法,实际上底层执行的是HurlStack或者HttpClientStack中的performRequest方法。若是执行HurlStackperformRequest方法,则底层其实是调用的HttpURLConnection;若是执行HttpClientStackperformRequest方法,则底层其实是调用的HttpConnection

    分发Response到主线程的逻辑与CacheDispatcher中的分发逻辑完全一致。

    使用单例来管理RequestQueue

    创建一个RequestQueue是非常消耗资源的,在一个Application中只需维护一个RequestQueue的实例就可以了。

    在写应用的时候,我们可以采用单例模式来管理RequestQueue的实例,节省资源的开销。

    发起一个标准的Volley网络请求

    标准的Volley请求有:

    StringRequestImageRequestJsonObjectRequest JsonArrayRequest

    区别就是new的对象和传的参数不一样

    1StringRequest

    StringRequest request = new StringRequest(

                        要访问的URL, 

                         new Response.Listener<String>() {},//请求结果正确返回的listener

                         new Response.ErrorListener() {});    //请求结果错误返回的lisetner

    2ImageRequest

    ImageRequest request = new ImageRequest(

                         要访问的URL, 

                         new Response.Listener<Bitmap>() {},    //请求结果正确返回的listener

                         0,         //压缩比,不想压缩就传0

                         0,         //压缩比,不想压缩就传0

                         null,     //伸缩,null不做任何处理

                        Bitmap.Config.RGB_565,     //想让图片显示的质量,RGB_565ARGB_8888ARGB_4444

                         new Response.ErrorListener() {});        //请求结果错误返回的listener

    3JsonObjectRequest

    JsonObjectRequest request = new JsonObjectRequest(

                         要请求的URL, 

                         params,        //要向服务器传入的参数

                        new Response.Listener<JSONObject>() {},      //请求结果正确返回的listener

                        new Response.ErrorListener() {});         //请求结果错误返回的listener

     

    4ImageLoader:不使用内存缓存,则给一个默认的ImageCache,不重写里面的方法

     mImageLoader = new ImageLoader(

                    mRequestQueue,         //请求队列

                   new ImageLoader.ImageCache() {重写getBitmapputBitmap});    //imageloader的缓存在普通缓存前执行

            使用ImageLoader加载图片

            mImageLoader.get(

                        URL,     //要请求图片的地址

                        ImageLoader.getImageListener(

                                    mIv,        //显示到哪

                                    R.mipmap.ic_launcher,     //默认显示图片的资源id

                                    R.mipmap.ic_launcher)    //请求失败显示的图片

                        );

    5NetworkImageView:加载网络图片 

    在布局文件中:

            <com.android.volley.toolbox.NetworkImageView

                android:id="@+id/niv"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:layout_centerInParent="true" />

    在代码中(前两步跟ImageLoader一样,最后一步如下):

            mNiv.setImageUrl(URL, mImageLoader);

     

    自定义request

    自定义Request需要实现两步:

           1. 继承Request<T>,其中T表示转换成的Response的类型

           2. 实现抽象方法 parseNetworkResponse()  deliverResponse()

     

     

     

    转载请注明原文地址: https://ju.6miu.com/read-6536.html

    最新回复(0)