Volley使用与源码解析

Volley 是一个专为 Android 设计的 HTTP 库,简化了网络请求并提高了响应速度,尤其适合高并发场景。不过,它不适用于大型下载或流媒体操作,因为所有响应都会被缓存在内存中。Volley 支持请求取消,自动调度,并在 data/data/app/cache 目录下存储数据。本文将涵盖 Volley 的 Get、Post、Json 请求、图片请求及其源码解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

依赖

implementation 'com.android.volley:volley:1.1.1'

Volley是一个HTTP库,它使Android应用程序的网络更容易,最重要的是,更快,适合高并发的网络请求。网络请求 cancel 机制。我们可以取消单个请求,或者指定取消请求队列中的一个区域;自动调度网络请求;
Volley不适合大型下载或流式操作,因为Volley在解析期间将所有响应保存在内存中。对于大型下载操作,请考虑使用类似的替代方法DownloadManager。
数据存储空间为data/data/app/cache 内,特点为系统将自动删除此目录中的文件,因为设备上的其他位置需要磁盘空间。
Get请求

String uriStr = "http://www.qubaobei.com/ios/cf/dish_list.php?stage_id=1&limit=20&page=1";
//创建一个请求队列
RequestQueue requestQueue = Volley.newRequestQueue(this);
//创建一个请求
StringRequest stringRequest = new StringRequest(uriStr, new Response.Listener<String>() {
    //接收数据回调
    @Override
    public void onResponse(String response) {
        Log.d("volley","onResponse"+response);
    }
}, new Response.ErrorListener() {
    //发生异常后的监听回调
    @Override
    public void onErrorResponse(VolleyError error) {
        Log.d("volley","onErrorResponse"+error);
    }
});
//将创建的请求添加到请求队列中
requestQueue.add(stringRequest);

Post请求

String uriStr = "http://www.qubaobei.com/ios/cf/dish_list.php?stage_id=1&limit=20&page=1";
//创建一个请求队列
RequestQueue requestQueue = Volley.newRequestQueue(this);
StringRequest stringRequest = new StringRequest(Request.Method.POST, uriStr, new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        Log.d("volley","onResponse"+response);
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        Log.d("volley","onErrorResponse"+error);
    }
});
//将创建的请求添加到请求队列中
requestQueue.add(stringRequest);

Json请求

String url = "http://192.168.3.6:8080/GetAndPostTest/MianTest";
// 1 创建一个请求队列
RequestQueue requestQueue = Volley.newRequestQueue(this);

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null, new Response.Listener<JSONObject>() {
    @Override
    public void onResponse(JSONObject jsonObject) {
        Log.e("AppDebug", "onResponse: "+jsonObject.toString());
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError volleyError) {
        Log.e("AppDebug", "onErrorResponse: "+volleyError);
    }
});

// 3 将创建的请求添加到请求队列中
requestQueue.add(jsonObjectRequest);

图片请求

// 1 创建一个请求队列
RequestQueue requestQueue1 = Volley.newRequestQueue(this);
// 2 创建一个图片的请求
String url = "http://img3.duitang.com/uploads/item/201510/11/20151011101817_fZ2hJ.thumb.700_0.jpeg";
ImageRequest imageRequest = new ImageRequest(url, new Response.Listener<Bitmap>() {
    @Override
    public void onResponse(Bitmap bitmap) {
        // 正确接收到图片
        imageView.setImageBitmap(bitmap);
    }
}, 0, 0, ImageView.ScaleType.CENTER, Bitmap.Config.RGB_565, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        //错误处理
    }
});
// 3 将请求添加到请求队列中
requestQueue.add(imageRequest);

源码解析

在这里插入图片描述

//StringRequest继承Request<泛型>
//提供有两个有参构造,在构造函数中一定要调用super()方法将这几个参数传给父类,因为HTTP的请求和响应都是在父类中自动处理的

public class StringRequest extends Request<String> {

    /** Lock to guard mListener as it is cleared on cancel() and read on delivery. */
    private final Object mLock = new Object();

    @Nullable
    @GuardedBy("mLock")
    private Listener<String> mListener;

    /**
     * Creates a new request with the given method.
     *
     * @param method the request {@link Method} to use
     * @param url URL to fetch the string at
     * @param listener Listener to receive the String response
     * @param errorListener Error listener, or null to ignore errors
     */
     //请求类型,请求地址,以及响应回调
    public StringRequest(
            int method,
            String url,
            Listener<String> listener,
            @Nullable ErrorListener errorListener) {
        super(method, url, errorListener);
        mListener = listener;
    }

    /**
     * Creates a new GET request.
     *
     * @param url URL to fetch the string at
     * @param listener Listener to receive the String response
     * @param errorListener Error listener, or null to ignore errors
     */
     //请求地址,响应回调
    public StringRequest(
            String url, Listener<String> listener, @Nullable ErrorListener errorListener) {
        this(Method.GET, url, listener, errorListener);
    }

    @Override
    public void cancel() {
        super.cancel();
        synchronized (mLock) {
            mListener = null;
        }
    }

//deliverResponse()方法中的实现,调用了mListener中的onResponse()方法,并将response内容,这样就可以将服务器响应的数据进行回调了
    @Override
    protected void deliverResponse(String response) {
    //获取Request中Listener接口
        Response.Listener<String> listener;
        synchronized (mLock) {
            listener = mListener;
        }
        if (listener != null) {
            listener.onResponse(response);
        }
    }

//parseNetworkResponse()方法中则应该对服务器响应的数据进行解析,其中数据是以字节的形式存放在NetworkResponse的data变量中的,这里将数据取出然后组装成一个String,并传入Response的success()方法中即可
  @Override
    @SuppressWarnings("DefaultCharset")
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        String parsed;
        try {
            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        } catch (UnsupportedEncodingException e) {
            // Since minSdkVersion = 8, we can't call
            // new String(response.data, Charset.defaultCharset())
            // So suppress the warning instead.
            parsed = new String(response.data);
        }
        return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
    }
}

volley

public class Volley {

    /** Default on-disk cache directory. */
    private static final String DEFAULT_CACHE_DIR = "volley";

    /**
     * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.
     *
     * @param context A {@link Context} to use for creating the cache dir.
     * @param stack A {@link BaseHttpStack} to use for the network, or null for default.
     * @return A started {@link RequestQueue} instance.
     */
    public static RequestQueue newRequestQueue(Context context, BaseHttpStack stack) {
        BasicNetwork network;
        //判断如果stack是等于null的,则去创建一个HttpStack对象
        if (stack == null) {
        //判断手机系统版本号是大于9的,则创建一个HurlStack的实例,否则就创建一个HttpClientStack的实例
            if (Build.VERSION.SDK_INT >= 9) {
                network = new BasicNetwork(new HurlStack());
            } else {
                // Prior to Gingerbread, HttpUrlConnection was unreliable.
                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                // At some point in the future we'll move our minSdkVersion past Froyo and can
                // delete this fallback (along with all Apache HTTP code).
                String userAgent = "volley/0";
                try {
                    String packageName = context.getPackageName();
                    PackageInfo info =
                            context.getPackageManager().getPackageInfo(packageName, /* flags= */ 0);
                    userAgent = packageName + "/" + info.versionCode;
                } catch (NameNotFoundException e) {
                }

	//创建了一个Network对象,用于根据传入的HttpStack对象来处理网络请求
                network =
                        new BasicNetwork(
                                new HttpClientStack(AndroidHttpClient.newInstance(userAgent)));
            }
        } else {
            network = new BasicNetwork(stack);
        }

        return newRequestQueue(context, network);
    }

    /**
     * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.
     *
     * @param context A {@link Context} to use for creating the cache dir.
     * @param stack An {@link HttpStack} to use for the network, or null for default.
     * @return A started {@link RequestQueue} instance.
     * @deprecated Use {@link #newRequestQueue(Context, BaseHttpStack)} instead to avoid depending
     *     on Apache HTTP. This method may be removed in a future release of Volley.
     */
    
    @Deprecated
    @SuppressWarnings("deprecation")
    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        if (stack == null) {
            return newRequestQueue(context, (BaseHttpStack) null);
        }
        return newRequestQueue(context, new BasicNetwork(stack));
    }
//new出一个RequestQueue对象,并调用它的start()方法进行启动,然后将RequestQueue返回
    private static RequestQueue newRequestQueue(Context context, Network network) {
        File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
        RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
        queue.start();
        return queue;
    }

    /**
     * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.
     *
     * @param context A {@link Context} to use for creating the cache dir.
     * @return A started {@link RequestQueue} instance.
     */
    public static RequestQueue newRequestQueue(Context context) {
        return newRequestQueue(context, (BaseHttpStack) null);
    }
}

start

public void start() {
//CacheDispatcher缓存线程NetworkDispatcher网络请求线程
    stop(); // Make sure any currently running dispatchers are stopped.
    // Create the cache dispatcher and start it.
    mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
    mCacheDispatcher.start();

    // Create network dispatchers (and corresponding threads) up to the pool size.
    for (int i = 0; i < mDispatchers.length; i++) {
        NetworkDispatcher networkDispatcher =
                new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery);
        mDispatchers[i] = networkDispatcher;
        networkDispatcher.start();
    }
}

add

public <T> Request<T> add(Request<T> request) {
    // Tag the request as belonging to this queue and add it to the set of current requests.
    request.setRequestQueue(this);
    synchronized (mCurrentRequests) {
        mCurrentRequests.add(request);
    }

    // Process requests in the order they are added.
    request.setSequence(getSequenceNumber());
    request.addMarker("add-to-queue");

    // If the request is uncacheable, skip the cache queue and go straight to the network.
    if (!request.shouldCache()) {
        mNetworkQueue.add(request);
        return request;
    }
    mCacheQueue.add(request);
    return request;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值