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 ...
随机推荐
- 获取week of year的小程序
#coding=utf8 import urllib, BeautifulSoup web=urllib.urlopen("http://whatweekisit.com/") s ...
- Codeforces 377
简单说一下. A 搜索出任意一个剩余细胞个数的联通块.剩下的填X. B 二分加贪心加数据结构. /* * Problem: * Author: Shun Yao */ #include <str ...
- j2ee的十三个规范
转载 今天在做连接oracle数据库的时候,感受到了什么是规范.平时听到别人说学习j2ee一定要学习他的十三个规范,大概的知道每个规范是做什么的,每个“接口”是做什么的. 很早就听过 ...
- Linux Oracle服务启动&停止脚本与开机自启动
在CentOS 6.3下安装完Oracle 10g R2,重开机之后,你会发现Oracle没有自行启动,这是正常的,因为在Linux下安装Oracle的确不会自行启动,必须要自行设定相关参数,首先先介 ...
- 【现代程序设计】【期末作业】【homework-09】
作业要求说明: http://www.cnblogs.com/xinz/p/3441537.html 我在做一个什么样的应用: 展示如何逐步求解一个加权矩阵的 最大子矩阵 任意联通图形 下面是软件的截 ...
- Oracle的回收站和闪回查询机制(二)
上一篇中讲诉了Oracle中一些闪回查询(Flashback Query),这是利用回滚段信息来恢复一个或一些表到以前的一个时间点(一个快照).要注意的是,Flashback Query仅仅是查询以前 ...
- HDU 5675 ztr loves math (数学推导)
ztr loves math 题目链接: http://acm.hust.edu.cn/vjudge/contest/123316#problem/A Description ztr loves re ...
- CodeForces 176B Word Cut (计数DP)
Word Cut Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Submit St ...
- osx升级到10.10后,用pod install报错最终解决办法
转载自:http://blog.csdn.net/liuyujinglove/article/details/40582197 http://blog.csdn.net/dqjyong/article ...
- Spring Data JPA 教程(翻译)
写那些数据挖掘之类的博文 写的比较累了,现在翻译一下关于spring data jpa的文章,觉得轻松多了. 翻译正文: 你有木有注意到,使用Java持久化的API的数据访问代码包含了很多不必要的模式 ...