依赖
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;
}