Java基础知识强化之网络编程笔记23:Android网络通信之 Volley(Google开源网络通信库)
联合网上资料学习:http://www.open-open.com/lib/view/open1451223702339.html
一、Volley的介绍
1. Volley简介
在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的Google I/O 2013上,Volley发布了。Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮。
这是Volley名称的由来: a burst or emission of many things or a large amount at once
在Google IO的演讲上,其配图是一幅发射火弓箭的图,有点类似流星。见下图:
其实,从这幅图,我们也可以看出来,Volley特别适合数据量不大但是通信频繁的场景。
2. Volley的引入背景:
在以前,我们可能面临如下很多麻烦的问题。
(1)比如以前从网上下载图片的步骤可能是这样的流程:
- 在ListAdapter#getView()里开始图像的读取。
- 通过AsyncTask等机制使用HttpURLConnection从服务器去的图片资源
- 在AsyncTask#onPostExecute()里设置相应ImageView的属性。
而在Volley下,只需要一个函数即可,详细见后面的例子。
(2)再比如,屏幕旋转的时候,有时候会导致再次从网络取得数据。为了避免这种不必要的网络访问,我们可能需要自己写很多针对各种情况的处理,比如cache什么的。
(3)再有,比如ListView的时候,我们滚动过快,可能导致有些网络请求返回的时候,早已经滚过了当时的位置,根本没必要显示在list里了,虽然我们可以通过ViewHolder来保持url等来实现防止两次取得,但是那些已经没有必须要的数据,还是会浪费系统的各种资源。
等等……
3. Volley提供的功能:
简单来说,它提供了如下的便利功能(优势):
• JSON,图像等的异步下载;
• 网络请求的排序(scheduling)
• 网络请求的优先级处理
• 缓存
• 多级别取消请求
• 和Activity和生命周期的联动(Activity结束时同时取消所有网络请求)
二、Volley的使用:
1. 引入Volley非常简单,首先,从git库先克隆一个下来:
git clone https://android.googlesource.com/platform/frameworks/volley
然后编译为jar包,再在自己的工程里import进来。
注意,这个库要求最低SDK版本为Froyo,即至少要设置android:minSdkVersion为 以上。
也可以从Github代码库中获取:https://github.com/mcxiaoke/android-volley
我自己也存放了Volley的jar包:http://download.csdn.net/detail/hebao5201314/9581002
2. Volley实现JSON字符串GET请求:
(1)构建一个RequestQueue
RequestQueue requestQueue=Volley.newRequestQueue(this);//这里的this指的是Context
(2)创建一个Request
(3)将Request 添加到RequestQueue
注:
在构建JsonObjectRequest
对象时,需要四个参数:
第一个参数代表http方法;
第二个参数代表访问Url;
第三个和第四个参数分别是 响应监听 和 响应错误监听,分别需要覆写onResponse()和onErrorResponse()方法;RequestQueue
将会执行请求,并将响应回调onResponse()
方法,所以需要在onResponse()方法中实现自己的业务逻辑。
代码如下:
//获取Json字符串
public void getJSONVolley() {
RequestQueue requestQueue = Volley.newRequestQueue(this);
String JSONDateUrl = "http://www.wwtliu.com/jsondata.html";
/**
* JsonObjectRequest(int method, String url, JSONObject jsonRequest,
* Listener<JSONObject> listener, ErrorListener errorListener)
*/
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, JSONDateUrl, null,
new Response.Listener<JSONObject>() { public void onResponse(JSONObject response) {
System.out.println("response="+response); } }, new Response.ErrorListener() {
public void onErrorResponse(com.android.volley.VolleyError arg0) {
System.out.println("对不起,有问题");
};
}
); requestQueue.add(jsonObjectRequest);
}
效果如下:
3. Volley实现异步加载图片:
(1)首先开启Apache服务器,在Apache服务器中存放一个图片text.jpg,如下:
使用360浏览器访问这个text.jpg文件,结果如下:
说明这里的Apache服务器是开启成功,可以正常访问。
(2)新建一个Android工程,命名为"MyVolley",如下:
(3)我们先看看布局文件activity_main.xml,如下:
这个布局是自适应显示图片的。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.himi.myvolley.MainActivity" > <ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="30dp"
android:layout_marginTop="16dp" /> </RelativeLayout>
(4)MainActivity.java:
package com.himi.myvolley; import org.json.JSONObject; import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.LruCache;
import android.widget.ImageView; import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageCache;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley; /**
* Volley是Android平台网络通信库:更快,更简单,更健壮。
* volley提供的功能:
* 1. JSON、图片(异步)
* 2. 网络请求的排序
* 3. 网络请求的优先级处理
* 4. 缓存
* 5. 多级别的取消请求
* 6. 与Activity生命周期联动(Activity结束时同时取消所有网络请求)
*
*
* 获取Volley()
* git clone https://android.googlesource.com/platform/frameworks/volley
*/
public class MainActivity extends Activity {
private ImageView iv1; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
//加载网络图片
loadImageVolley();
} public void init() {
iv1 = (ImageView) findViewById(R.id.iv);
} //异步加载图片 public void loadImageVolley() {
String imageurl = "http://49.123.72.145/text.jpg";
RequestQueue requestQueue = Volley.newRequestQueue(this);
final LruCache<String, Bitmap> lurcache = new LruCache<String, Bitmap>(20);
ImageCache imageCache = new ImageCache() { //返回当前图片
public Bitmap getBitmap(String key) {
return lurcache.get(key);
} //缓存图片资源
public void putBitmap(String key, Bitmap value) {
lurcache.put(key, value);
} }; ImageLoader imageLoader = new ImageLoader(requestQueue, imageCache);
/**
* getImageListener(ImageView view, int defaultImageResId, int errorImageResId)
*
*/
ImageListener listener = imageLoader.getImageListener(iv1, R.drawable.ic_launcher,
R.drawable.ic_launcher);
imageLoader.get(imageurl, listener);
} }
这里要使用到网络,所以我们这里在AndroidMainfest.xml添加网络权限,如下:
<uses-permission android:name="android.permission.INTERNET"/>
(5)布署程序到模拟器上,如下:
4. Volley使用NetWorkImageView:
Volley提供了一个新的控件NetworkImageView来代替传统的ImageView,这个控件的图片属性可以通过:
mImageView.setImageUrl(url, imageLoader)
来设定。而且,这个控件在被从父控件detach的时候,会自动取消网络请求的,即完全不用我们担心相关网络请求的生命周期问题。
(1)这里我们3的项目中展示NetWorkImageView的使用,如下我们首先来到布局文件activity_main.xml,如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.himi.myvolley.MainActivity" > <ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="30dp"
android:layout_marginTop="16dp" /> <com.android.volley.toolbox.NetworkImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
/> </RelativeLayout>
(2)然后是MainActivity.java,如下:
package com.himi.myvolley; import org.json.JSONObject; import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.LruCache;
import android.widget.ImageView; import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageCache;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.Volley; /**
* Volley是Android平台网络通信库:更快,更简单,更健壮。
* volley提供的功能:
* 1. JSON、图片(异步)
* 2. 网络请求的排序
* 3. 网络请求的优先级处理
* 4. 缓存
* 5. 多级别的取消请求
* 6. 与Activity生命周期联动(Activity结束时同时取消所有网络请求)
*
*
* 获取Volley()
* git clone https://android.googlesource.com/platform/frameworks/volley
*/
public class MainActivity extends Activity {
private ImageView iv1;
private NetworkImageView iv2; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
//getJSONVolley();
NetWorkImageViewVolley(); } public void init() {
iv1 = (ImageView) findViewById(R.id.iv);
iv2 = (NetworkImageView) findViewById(R.id.imageView1);
loadImageVolley();
} //获取Json字符串
public void getJSONVolley() {
RequestQueue requestQueue = Volley.newRequestQueue(this);
String JSONDateUrl = "http://www.wwtliu.com/jsondata.html";
/**
* JsonObjectRequest(int method, String url, JSONObject jsonRequest,
* Listener<JSONObject> listener, ErrorListener errorListener)
*/
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, JSONDateUrl, null,
new Response.Listener<JSONObject>() { public void onResponse(JSONObject response) {
System.out.println("response="+response); } }, new Response.ErrorListener() {
public void onErrorResponse(com.android.volley.VolleyError arg0) {
System.out.println("对不起,有问题");
};
}
); requestQueue.add(jsonObjectRequest);
} //异步加载图片
//http://localhost/lesson-img.png
public void loadImageVolley() {
String imageurl = "http://49.123.72.145/text.jpg";
RequestQueue requestQueue = Volley.newRequestQueue(this);
final LruCache<String, Bitmap> lurcache = new LruCache<String, Bitmap>(20);
ImageCache imageCache = new ImageCache() { //返回当前图片
public Bitmap getBitmap(String key) {
return lurcache.get(key);
} //缓存图片资源
public void putBitmap(String key, Bitmap value) {
lurcache.put(key, value);
} }; ImageLoader imageLoader = new ImageLoader(requestQueue, imageCache);
/**
* getImageListener(ImageView view, int defaultImageResId, int errorImageResId)
*
*/
ImageListener listener = imageLoader.getImageListener(iv1, R.drawable.ic_launcher,
R.drawable.ic_launcher);
imageLoader.get(imageurl, listener);
}
// Volley使用NetWorkImageView
public void NetWorkImageViewVolley() {
String imageUrl = "http://49.123.72.145/text.jpg";
RequestQueue requestQueue = Volley.newRequestQueue(this);
final LruCache<String, Bitmap> lruCache = new LruCache<String, Bitmap>(20);
ImageCache imageCache = new ImageCache() { public Bitmap getBitmap(String key) {
// TODO 自动生成的方法存根
return lruCache.get(key);
} public void putBitmap(String key, Bitmap value) {
lruCache.put(key, value); } }; ImageLoader imageLoader = new ImageLoader(requestQueue, imageCache);
iv2.setTag("url");
iv2.setImageUrl(imageUrl, imageLoader);
} }
其他代码不变,布署程序到模拟器上,效果如下:
5. Volley的框架原理:
Volley使用了线程池来作为基础结构,主要分为主线程,cache调度线程和 network调度线程。
主线程 和 cache调度线程 都只有一个,而network调度线程可以有多个,这样能解决比并行问题。如下图:
• 优点:Volley简化了网络通信这块的开发,特别是针对数据量不大但网络通信频繁,对JSON对象,图片加载这两块进行了很好的封装和支持,
• 缺点:对大数据(large payloads ),流媒体,这些case不能很好的支持,还需要使用原始的方法,比如Download Manager等。
其中蓝色的是主线程,绿色的是缓存线程,黄色的是网络线程
(1)当一个Request请求添加到RequestQueue请求队列中,Volley就开始工作了。RequestQueue请求队列中持有一个CacheDispatcher缓存调度器和一组NetworkDispatcher网络调度器。
(2)RequestQueue会先叫来CacheDispatcher缓存调度器,让他去看看,当前请求的数据在不在cache中。
2.1.当前的数据在cache中,那就把数据从cache中取出来,然后经过一番加工,将加工好的数据交付给主线程
2.2.当前数据没在cache中,进行第3步
(3)进行到了这一步,那肯定是数据没有在缓存中,那只能去网络中获取了,这时候RequestQueue会叫来NetworkDispatcher网络调度器,NetworkDispatcher可是有一大帮子呢,其实这是一个线程池,默认情况下会启动4个线程去网络下载数据。所以RequestQueue把当前闲着的NetworkDispatcher叫来,给他们分配任务。
(4)拿到任务的NetworkDispatcher就会去网络上下载数据了,与此同时,他会判断下载到的数据能否写入到cache缓存中,如果可以的话就写入cache,以便于下一次直接从cache中获取到数据。最后,将数据加工,交付给主线程。
如果在一个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());
...
Java基础知识强化之网络编程笔记23:Android网络通信之 Volley(Google开源网络通信库)的更多相关文章
- Java基础知识强化之网络编程笔记21:Android网络通信之 Android常用OAuth登录(获取令牌信息)
1. 首先我们去下载开发相关SDK(Android): 下载百度使用OAuth的SDK(Android),如下: 下载链接为:http://developer.baidu.com/wiki/index ...
- Java基础知识强化之网络编程笔记18:Android网络通信之 使用HttpClient的Post / Get 方式读取网络数据(基于HTTP通信技术)
使用HttpClient进行Get方式通信,通过HttpClient建立网络链接,使用HttpGet方法读取数据,并且通过Response获取Entity返回值. 使用HttpClient进行Post ...
- Java基础知识强化之网络编程笔记17:Android网络通信之 使用Http的Post方式读取网络数据(基于HTTP通信技术)
使用Http的Post方式与网络交互通信.Post方式需要向网络传输一部分数据,同时具有输入流和输出流. 详见:Android(java)学习笔记210:采用post请求提交数据到服务器(qq登录案例 ...
- Java基础知识强化之网络编程笔记16:Android网络通信之 使用Http的Get方式读取网络数据(基于HTTP通信技术)
使用Http的Get方式读取网络数据,使用Get方式与网络通信是最常见的Http通信,建立链接之后就可以通过输入流读取网络数据. 详见:Android(java)学习笔记209:采用get请求提交数据 ...
- Java基础知识强化之网络编程笔记19:Android网络通信之 HttpClient和传统Post、Get方式的区别
1. HttpClient是什么 ? HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源.虽然在 ...
- Java基础知识强化之网络编程笔记01:InetAddress类的概述和使用
1. InetAddress类 InetAddress是Java对IP地址的封装,在java.net中有许多类都使用到了InetAddress,包括ServerSocket,Socket,Datagr ...
- Java基础知识强化之网络编程笔记25:Android网络通信之 Future接口介绍(Java程序执行超时)
1. Future接口简介 在Java中,如果需要设定代码执行的最长时间,即超时,可以用Java线程池ExecutorService类配合Future接口来实现. Future接口是Java标准API ...
- Java基础知识强化之网络编程笔记24:Android网络通信之 AndroidAsync(基于nio的异步通信库)
1. AndroidAsync AndroidAsync 是一个基于nio的异步socket ,http(客户端服务器端),websocket,socket.io库,AndroidAsync 是一 ...
- Java基础知识强化之网络编程笔记22:Android网络通信之 Android常用OAuth登录(获取个人信息)
1. 获取百度个人信息(使用Gson解析): 2. 代码案例: (1)工程一览图,如下: (2)activity_main.xml: <LinearLayout xmlns:android=&q ...
随机推荐
- CDH5.5.1 安装Spark ON Yarn环境
CDH对我们已经封装了,我们如果需要Spark on Yarn,只需要yum安装几个包就可以了. 前面的文章我有写过如果搭建自己内网的CDH Yum服务器,请参考<CDH 5.5.1 Yum源服 ...
- google proto buffer安装和简单示例
1.安装 下载google proto buff. 解压下载的包,并且阅读README.txt,根据里面的指引进行安装. $ ./configure $ make $ make check $ mak ...
- homework-08-作业2
1. 了解Lambda的用法 计算“Hello World!”中 a.字母‘e’的个数 b. 字母‘l’的个数 代码: void calcEL() { char s[100] = "Hell ...
- 精通Linux的“kill”命令
无论你使用哪种操作系统,你一定会遇到某个行为失常的应用,它把自己锁死并拒绝关闭.在Linux(还有Mac),你可以用一个"kill"命令强制终结它.在这个教程中,我们将展示给你多种 ...
- ucGUI例程收藏
ucGUI 几个重要例程Demo 按钮的定制 #include <stddef.h> #include <string.h> #include "WM.h&quo ...
- HDU 3661 Assignments (水题,贪心)
题意:n个工人,有n件工作a,n件工作b,每个工人干一件a和一件b,a[i] ,b[i]代表工作时间,如果a[i]+b[j]>t,则老板要额外付钱a[i]+b[j]-t;现在要求老板付钱最少: ...
- pymol编译
https://pymolwiki.org/index.php/Linux_Install
- SQL中DATE和DATETIME类型不能直接作比较
如题,今天纠结了一天的问题. 在存储过程中定义了两个datetime类型的时间,然后把这个两个时间作为where条件中一个date字段between的两个时间段,结果无论如何都不执行... 就像 u ...
- request,response,session
1.request.getParameter("key")接受的是来自客户登陆端的数据,接受的是post或get方式传送的value. 2.请求的默认字符集是ISO-8859-1, ...
- JavaEE通过response实现请求重定向
请求重定向指的是一个web资源收到客户端请求后,通知客户端去访问另外一个web资源,这称之为请求重定向.302状态码和location头即可实现重定向. 请求重定向最常见的应用场景就是用户登录. 下面 ...