本文内容
- 什么是 Volley 库
- Volley 能做什么
- Volley 架构
- 环境
- 演示 Volley 库的使用
- 参考资料
Android 关于网络操作一般都会介绍 HttpClient 以及 HttpConnection 这两个包。前者是 Apache 开源库,后者是 Android 自带 API。企业级应用,一般都会选择使用已经封装好的 http 框架。比较流行有 Volley、android-async-http、retrofit、okhttp、androidquery、AndroidAsync 等。他们各有特点,不同的框架有不同的效率,如今 Google 推出了官方的针对 Android 平台上的网络通信库 Volley,能使网络通信更快,更简单,更健壮,Volley 在提供了高性能网络通讯功能的同时,对网络图片加载也提供了良好的支持,完全可以满足简单 REST 客户端的需求。另外,但 Volley 扩展性很强,可以根据需要定制你自己的网络请求。
什么是 Volley 库
Volley 是 Ficus Kirpatrick 在 Gooogle I/O 2013 发布的一个处理和缓存网络请求的库,能使网络通信更快,更简单,更健壮。Volley 名称的由来 a burst or emission of many things or a large amount at once。在Gooogle I/O 2013 演讲上,其配图是一幅火弓箭。如图 1 所示。
图 1 Gooogle I/O 2013 Volley
Volley 管理着处理和缓存网络请求,它节省了开发者的宝贵时间,一次又一次编写相同的网络调用/缓存代码。更少的重复代码,其中一个好处就是减少了 bug,这是所有开发者所期望的。
所谓“一次又一次编写相同的网络调用/缓存代码”,就是 AsyncTask 以及你编写的通过 Web API 获取响应,并显示出来的逻辑/代码。我们必须在 ProgressBar() 和 onPostExecute() 方法内照顾 ProgressBar/ProgressDialog 。虽然这不是一个艰巨的任务,但却很无聊,甚至感到厌倦,尽管我已经定义了 BaseTask 类来管理ProgressBar/ProgressDialog 的显示/取消,以及更多其它操作。现在,Volley 是替代 AsyncTask 的强大工具。
Volley 能做什么
Volley 适合小而快的数据传输,特别是针对以下两种情况:
- JSON 对象
- 图片加载
Volley 优势:
- Volley 可以自动安排所有的网络请求。这意味着 Volley 会照顾你 APP 执行的从 Web 获取响应或图片所有的网络请求。
- Volley 提供透明的磁盘和内存缓存。
- Volley 提供强大的取消请求的 API。这意味着你可以取消一个单独的请求,或是你可以设置取消请求的块(可以为多个)或范围。
- Volley 提供强大的自定功能。
- Volley 提供调试和追踪工具。
Volley 架构
Volley 使用了线程池来作为基础结构,主要分为主线程,cache 线程和 network 线程。主线程和 cache 线程都只有一个,而 NetworkDispatcher 线程可以有多个,这样能解决比并行问题。
图 2 Volley 架构
环境
- Windows 2008 R2 64 位
- Eclipse ADT V22.6.2,Android 4.4.3
- 三星 SM-G3508,Android OS 4.1
演示 Volley 库的使用
下载演示,将 Volley 库和演示项目导入到 eclipse 里,再将 Volley 库添加到演示项目。程序运行结果如图 3 所示,包含两个演示:网络获取 JSON 和 图片。
图 3 左:程序主界面;中:点击“获取 JSON”;右:点击“获取 Image”
主程序 activity_main.xml 界面包含两个按钮,显示两个演示的 activity,核心代码如下所示:
public class MainActivity extends Activity {
Intent intent = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_json).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
intent = new Intent(MainActivity.this, JsonDemo.class);
startActivity(intent);
}
});
findViewById(R.id.btn_img).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
intent = new Intent(MainActivity.this, ImgDemo.class);
startActivity(intent);
}
});
}
}
授权 Android 访问网络权限
修改 AndroidManifest.xml 文件,添加授权 Android 访问网络的权限。
<uses-permission android:name="android.permission.INTERNET" />
获取 JSON
通过 Volley 访问国家气象局提供的 JSON 接口,获得北京的天气状况。
- http://www.weather.com.cn/data/sk/101010100.html
http://www.weather.com.cn/data/cityinfo/101010100.html
http://m.weather.com.cn/data/101010100.html
其中,101010100 代表北京。
activity_json.xml 页面文件包含一个 TextView 控件和一个 ProgreeBar 控件,略,核心代码如下所示:
package com.example.volleyexample;
import android.app.Activity;
import org.json.JSONObject;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class JsonDemo extends Activity {
private TextView txtDisplay;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_json);
txtDisplay = (TextView) findViewById(R.id.txtDisplay);
RequestQueue queue = Volley.newRequestQueue(this);
String url = "http://www.weather.com.cn/data/sk/101010100.html";
JsonObjectRequest jsObjRequest = new JsonObjectRequest(
Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
// TODO Auto-generated method stub
txtDisplay.setText("Response => " + response.toString());
findViewById(R.id.progressBar1)
.setVisibility(View.GONE);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
});
queue.add(jsObjRequest);
}
}
获取 image
activity_img.xml 页面文件包含两个控件:ImageView 和 NetworkImageView,其中,NetworkImageView 是 Volley 提供的控件,毕竟加载图片的使用频率很高,略,核心代码如下所示:
package com.example.volleyexample;
import org.json.JSONObject;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
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.NetworkImageView;
import com.android.volley.toolbox.Volley;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.util.LruCache;
import android.widget.ImageView;
public class ImgDemo extends Activity {
String url = "http://images.cnblogs.com/cnblogs_com/liuning8023/588559/o_Android.jpg";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_img);
RequestQueue mRequestQueue = Volley.newRequestQueue(this);
final LruCache<String, Bitmap> mImageCache = new LruCache<String, Bitmap>(
20);
ImageCache imageCache = new ImageCache() {
@Override
public void putBitmap(String key, Bitmap value) {
mImageCache.put(key, value);
}
@Override
public Bitmap getBitmap(String key) {
return mImageCache.get(key);
}
};
ImageLoader mImageLoader = new ImageLoader(mRequestQueue, imageCache);
// ImageView
ImageView img = (ImageView) findViewById(R.id.imgView);
ImageListener listener = ImageLoader
.getImageListener(img, android.R.drawable.ic_menu_rotate,
android.R.drawable.ic_delete);
mImageLoader.get(url, listener);
// NetworkImageView
NetworkImageView netImgView = (NetworkImageView) findViewById(R.id.networkImgView);
netImgView.setTag("url");
netImgView.setImageUrl(url, mImageLoader);
}
}