本博客:http://blog.csdn.net/xiaowu_zhu/article/details/70141015
Volley是在Google/IO大会上提出的,使得android应用网络操作更方便快捷
Volley既可以非常简单的访问网络,也可以轻松的加载图片,在不同的线程上异步执行所有请求而避免了阻塞主线程
设计目标: 适合数据量不大但通信操作频繁的网络操作,不适合大数据量的网络操作,比如文件下载
Velloy中的RequestQueue和Request
Request对象主要有以下几种类型:
基本使用
创建一个RequestQueue实例
//这里的this指的是Context
RequestQueue requestQueue = Volley.newRequestQueue(this);
创建一个Request(义JsonObjectRequest为例,其它几个类似)
private final String url="http:/xxxxx"//所需url
JsonObjectRequest req=new JsonObjectRequest(url,null,new Response.Listener(){
@Override
public void onResponse(JsonObject response){
//添加自己的响应逻辑,
}
},
new ResponseError.Listener(){
@Override
public void onResponseError(VollerError error){
//错误处理
L.d("Error Message:","Error is"+error);
}
});
将request实例添加到requestQueue中
requestQueue.add(jsonObjectRequest);
ImageLoader
ImageLoader比ImageRequest更加高效,它不仅可以图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。
由于ImageLoader不是继承Request的所以它的使用发送和以前不同,步骤如下:
创建一个RequestQueue对象
//这里的this指的是Context
RequestQueue requestQueue = Volley.newRequestQueue(this);
创建一个ImageLoader对象
ImageLoader imageLoader = new ImageLoader(mQueue, new ImageCache() {
@Override
public void putBitmap(String url, Bitmap bitmap) {
}
@Override
public Bitmap getBitmap(String url) {
return null;
}
});
获取一个ImageListerner对象
ImageListener listener = ImageLoader.getImageListener(imageView,
R.drawable.default_image, R.drawable.failed_image);
调用ImageLoader的get()方法加载网络上的图片
imageLoader.get("https://img-my.csdn.net/uploads/201404/13/1397393290_5765.jpeg", listener);
//重载
mageLoader.get("https://img-my.csdn.net/uploads/201404/13/1397393290_5765.jpeg",
listener, 200, 200);
为了很好的缓存图片,借助Android提供的LruCache功能,创建一个ImageCache
新建一个BitmapCache并实现ImageCache接口
public class BitmapCache implements ImageCache {
private LruCache mCache;
public BitmapCache() {
int maxSize = 10 * 1024 * 1024;
mCache = new LruCache(maxSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight();
}
};
}
@Override
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
mCache.put(url, bitmap);
}
}
NetworkImageView的用法
除了ImageReqeust和ImageLoader外,Volley还提供了NetworkImageView。NetworkImageView是一个自定义控制,它继承自ImageView,具备ImageView控件的所有功能,并且在原生的基础之上加入了加载网络图片的功能。NetworkImageView控件的用法简单,步骤如下:
其中,第一第二步和ImageLoader的用法是完全一样的,因此这里我们就从第三步开始学习了。首先修改布局文件中的代码,在里面加入NetworkImageView控件,如下所示:
接着在Activity获取到这个控件的实例,这就非常简单了,代码如下所示:
networkImageView = (NetworkImageView) findViewById(R.id.network_image_view);
得到了NetworkImageView控件的实例之后,我们可以调用它的setDefaultImageResId()方法、setErrorImageResId()方法和setImageUrl()方法来分别设置加载中显示的图片,加载失败时显示的图片,以及目标图片的URL地址,如下所示:
networkImageView.setDefaultImageResId(R.drawable.default_image);
networkImageView.setErrorImageResId(R.drawable.failed_image);
networkImageView.setImageUrl("https://img-my.csdn.net/uploads/201404/13/1397393290_5765.jpeg",
imageLoader);
关闭
如果在一个Activity里面启动了网络请求,而在这个网络请求还没返回结果的时候,如果Activity被结束了,则我们需要写如下代码作为防守:
@Override public void onPostExecute(Result r) {
if (getActivity() == null) {
return;
}
// ...
}
Activity被终止之后,如果继续使用其中的Context等,除了无辜的浪费CPU,电池,网络等资源,有可能还会导致程序crash,所以,我们需要处理这种一场情况。
使用Volley的话,我们可以在Activity停止的时候,同时取消所有或部分未完成的网络请求。
Volley里所有的请求结果会返回给主进程,如果在主进程里取消了某些请求,则这些请求将不会被返回给主线程。
比如,可以针对某些个request做取消操作:
@Override
public void onStop() {
for (Request > req : mInFlightRequests) {
req.cancel();
}
...
}
或者,取消这个队列里的所有请求:
@Override pubic void onStop() {
mRequestQueue.cancelAll(this);
...
}
也可以根据RequestFilter或者Tag来终止某些请求:
@Override
public void onStop() {
mRequestQueue.cancelAll( new RequestFilter() {})
...
// or
mRequestQueue.cancelAll(new Object());
...
}
Android Studio 配置gradle环境:
compile 'com.squareup.okhttp3:okhttp:3.5.0'
compile 'com.squareup.okio:okio:1.11.0'
添加网络权限
Http Get
异步的Get
在Http请求中最常见的就是get方法了,在大多数的使用场景中,我们使用的都是异步的Get请求
// step 1: 创建 OkHttpClient 对象
OkHttpClient okHttpClient = new OkHttpClient();
// step 2: 创建一个请求,不指定请求方法时默认是GET。
Request.Builder requestBuilder = new Request.Builder().url("http://www.baidu.com");
//可以省略,默认是GET请求
requestBuilder.method("GET",null);
// step 3:创建 Call 对象
Call call = okHttpClient.newCall(requestBuilder.build());
//step 4: 开始异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// TODO: 17-1-4 请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// TODO: 17-1-4 请求成功
//获得返回体
ResponseBody body = response.body();
}
});
文件下载
//step 1: 不变的第一步创建 OkHttpClick
OkHttpClient okHttpClient = new OkHttpClient();
//step 2: 创建Requset
Request request = new Request.Builder()
.url("http://www.ssyer.com/uploads/org_2017010593503_775.jpg")
.build();
//step 3:建立联系,创建Call
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) {
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = null;
try {
File file = new File(Environment.getExternalStorageDirectory() + "大狮子.jpg");
fileOutputStream = new FileOutputStream(file);
byte[] buffer = new byte[2048];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
}
fileOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
Log.d("downloadAsynFile", "文件下载成功");
}
});
同步的Get
当然 Get 也支持阻塞方式的同步请求,不过在开发中这种方法很少被使用。上面我们也说了Call有一个 execute() 方法,你也可以直接调用 call.execute() 返回一个 Response 。然后利用 isSuccessful() 判读是否成功,进行相应的结果解析。
异步的Http Post
Post 上传键值对
//step 1: 同样的需要创建一个OkHttpClick对象
OkHttpClient okHttpClient = new OkHttpClient();
//step 2: 创建 FormBody.Builder
FormBody formBody = new FormBody.Builder()
.add("name", "dsd")
.build();
//step 3: 创建请求
Request request = new Request.Builder().url("http://www.baidu.com")
.post(formBody)
.build();
//step 4: 建立联系 创建Call对象
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// TODO: 17-1-4 请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// TODO: 17-1-4 请求成功
}
});
在使用 Post 的时候,参数是包含在请求体中的。所以我们通过 FormBody ,添加多个String键值对,然后为 Request 添加 post(formBody) 完成我们 Request 的构造。之后的步骤就和Get的步骤一样了,是不是很简单啊!
Post异步上传文件
// step 1: 创建 OkHttpClient 对象
OkHttpClient okHttpClient = new OkHttpClient();
//step 2:创建 RequestBody 以及所需的参数
//2.1 获取文件
File file = new File(Environment.getExternalStorageDirectory() + "test.txt");
//2.2 创建 MediaType 设置上传文件类型
MediaType MEDIATYPE = MediaType.parse("text/plain; charset=utf-8");
//2.3 获取请求体
RequestBody requestBody = RequestBody.create(MEDIATYPE, file);
//step 3:创建请求
Request request = new Request.Builder().url("http://www.baidu.com")
.post(requestBody)
.build();
//step 4 建立联系
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// TODO: 17-1-4 请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// TODO: 17-1-4 请求成功
}
});
//添加权限
---------------------------------------------------------------------------
参数 说明
text/html HTML格式
text/plain 纯文本格式
text/xml XML格式
image/gif gif图片格式
image/jpeg jpg图片格式
image/png png图片格式
application/xhtml+xml XHTML格式
application/xml XML数据格式
application/atom+xml Atom XML聚合格式
application/json JSON数据格式
application/pdf pdf格式
application/msword Word文档格式
application/octet-stream 二进制流数据