访问网络的框架(Volley和OkHttp3)使用
本博客:http://blog.csdn.net/xiaowu_zhu/article/details/70141015
Volley
Volley是在Google/IO大会上提出的,使得android应用网络操作更方便快捷
Volley既可以非常简单的访问网络,也可以轻松的加载图片,在不同的线程上异步执行所有请求而避免了阻塞主线程
设计目标: 适合数据量不大但通信操作频繁的网络操作,不适合大数据量的网络操作,比如文件下载
使用
Velloy中的RequestQueue和Request
- RequestQueue用来执行请求的请求队列
- Request用来构造一个请求对象
Request对象主要有以下几种类型:
- StringReqeust 响应的主体为字符串
- JsonArrayReqeust 发送和接收JSON对象
- JsonObjectRequest发送和接收Json对象
- ImageRequest发送和接收Image
基本使用
创建一个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<JsonObject>(){ @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<String, Bitmap> mCache; public BitmapCache() { int maxSize = 10 * 1024 * 1024; mCache = new LruCache<String, Bitmap>(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控件的用法简单,步骤如下:
- 创建一个RequestQueue对象
- 创建一个ImageLoader对象
- 在布局文件中添加一个NetworkImageView控件
- 在代码中获取该控件的实例
- 设置要加载的图片地址
其中,第一第二步和ImageLoader的用法是完全一样的,因此这里我们就从第三步开始学习了。首先修改布局文件中的代码,在里面加入NetworkImageView控件,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send Request" /> <com.android.volley.toolbox.NetworkImageView android:id="@+id/network_image_view" android:layout_width="200dp" android:layout_height="200dp" android:layout_gravity="center_horizontal" /> </LinearLayout>
接着在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()); ... }
OkHttp3
Android Studio 配置gradle环境:
compile 'com.squareup.okhttp3:okhttp:3.5.0' compile 'com.squareup.okio:okio:1.11.0'
添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
使用教程
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 请求成功 } }); //添加权限 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> --------------------------------------------------------------------------- 参数 说明 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 二进制流数据