Volley 是 Google 推出的 Android 异步网络请求框架和图片加载框架。在 Google I/O 2013 大会上发布。关于Volley的详细解析可以参考:http://www.codekk.com/open-source-project-analysis/detail/Android/grumoon/Volley%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90
我们经常需要从网络获取数据,如字符串,图片和json等,多数情况下应用程序都会使用HTTP协议来发送和接收网络数据。Android系统中主要提供了两种方式来进行HTTP通信,HttpURLConnection和HttpClient,如果不进行适当封装的话,很容易就会写出不少重复代码。Volley就是一个将HTTP通信操作进行封装的网络通信框架,我们使用它只需要几步简单的操作就能实现想要的功能。
1,StringRequest、JsonRequest、ImageRequest的简单使用
这三个request的使用基本只需要三个步骤:
1)获取一个RequestQueue对象
2)创建一个Request对象(StringRequeust, JsonRequest, ImaeRequest)
3)将Request对象添加到RequestQueue中
public class MainActivity extends Activity implements OnClickListener{
private Context mContext = this;
private TextView mContentTv;
private ImageView mImageIv;
private Button mImageLoaderButton;
private Button mNetworkImageViewButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
setListener();
//1,需要获取一个RequestQueue对象
RequestQueue mQueue = Volley.newRequestQueue(mContext);
//2,创建一个StringRequest对象(这里使用的是get方式)
StringRequest stringRequest = new StringRequest("http://www.baidu.com", new Response.Listener<String>() {
//服务器响应成功回调
@Override
public void onResponse(String response) {
mContentTv.setText(response);
}
}, new Response.ErrorListener() {//服务器响应失败回调
@Override
public void onErrorResponse(VolleyError error) {
mContentTv.setText(error.getMessage());
}
});
//2,创建一个StringRequest对象(这里使用post方法)
StringRequest stringRequest2 = new StringRequest(Method.POST, "http://www.baidu.com", new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// TODO Auto-generated method stub
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
}){
//设置参数
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<>();
map.put("name", "wenhao");
map.put("age", "12");
return map;
}
};
//2,创建一个JsonRequest对象
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("http://m.weather.com.cn/data/101010100.html", new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
mContentTv.setText(response.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mContentTv.setText(error.getMessage());
}
});
//2,创建一个ImageRequest对象
/*
* ImageRequest的构造函数接收六个参数,第一个参数就是图片的URL地址,这个没什么需要解释的。
* 第二个参数是图片请求成功的回调,这里我们把返回的Bitmap参数设置到ImageView中。第三第四个参数
* 分别用于指定允许图片最大的宽度和高度,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,
* 指定成0的话就表示不管图片有多大,都不会进行压缩。第五个参数用于指定图片的颜色属性,
* Bitmap.Config下的几个常量都可以在这里使用,其中ARGB_8888可以展示最好的颜色属性,
* 每个图片像素占据4个字节的大小,而RGB_565则表示每个图片像素占据2个字节大小。第六个参数是图片请求失败的回调,
* 这里我们当请求失败时在ImageView中显示一张默认图片。
* */
@SuppressWarnings("deprecation")
ImageRequest imageRequest = new ImageRequest("http://t12.baidu.com/it/u=4095575894,102452705&fm=32&s=A98AA55F526172A6F6A058E50300A060&w=623&h=799&img.JPEG",
new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
mImageIv.setImageBitmap(response);
}
}, 0, 0, Config.RGB_565, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mImageIv.setImageResource(R.drawable.ic_launcher);
}
});
//3,将Request对象添加到RequestQueue中
//mQueue.add(stringRequest);
//mQueue.add(jsonObjectRequest);
mQueue.add(imageRequest);
}
private void initView(){
mContentTv = (TextView)findViewById(R.id.content);
mImageIv = (ImageView)findViewById(R.id.image);
mImageLoaderButton = (Button)findViewById(R.id.imageloader_button);
mNetworkImageViewButton = (Button)findViewById(R.id.network_image_view);
}
private void setListener(){
mImageLoaderButton.setOnClickListener(this);
mNetworkImageViewButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.imageloader_button:
Intent intent = new Intent(mContext,ImageLoaderActivity.class);
startActivity(intent);
break;
case R.id.network_image_view:
Intent intent2 = new Intent(mContext,NetworkImageViewActivity.class);
startActivity(intent2);
break;
default:
break;
}
}
}
2,ImageLoader的使用
ImageLoader也可以用于加载网络上的图片,并且它的内部也是使用ImageRequest来实现的,不过ImageLoader明显要比ImageRequest更加高效,因为它不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。它的使用可以总结为四个步骤:
1)创建RequestQueue对象
2)创建ImageLoader对象
3)获取一个ImageListener对象
4)调用ImgeLoader的get方法来加载图片
public class ImageLoaderActivity extends Activity{
private Context mContext = this;
private ImageView mImageIv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.imageloader_activity);
initView();
//1,创建RequestQueue对象
RequestQueue requestQueue = Volley.newRequestQueue(mContext);
//2,创建ImageLoader对象
ImageLoader imageLoader = new ImageLoader(requestQueue, new MyImageCache());
//3,获取一个ImageListener对象
/*
* ImageLoader的getImageListener()方法能够获取到一个ImageListener对象,
* getImageListener()方法接收三个参数,第一个参数指定用于显示图片的ImageView控件,
* 第二个参数指定加载图片的过程中显示的图片,
* 第三个参数指定加载图片失败的情况下显示的图片。*/
ImageListener imageListener = ImageLoader.getImageListener(mImageIv, R.drawable.image_default, R.drawable.image_err);
//4,调用ImageLoader的get方法来加载图片
//imageLoader.get("http://t12.baidu.com/it/u=4095575894,102452705&fm=32&s=A98AA55F526172A6F6A058E50300A060&w=623&h=799&img.JPEG", imageListener);
//也可以使用get()方法的重载,指定图片允许的最大宽度和高度
imageLoader.get("http://t12.baidu.com/it/u=4095575894,102452705&fm=32&s=A98AA55F526172A6F6A058E50300A060&w=623&h=799&img.JPEG", imageListener,200,200);
}
private void initView(){
mImageIv = (ImageView)findViewById(R.id.image);
}
}
/**
*ImageLoader中的ImageCache是个接口,我们可以通过实现该接口来实现图片缓存,
*推荐使用android提供的LruCache
* */
public class MyImageCache implements ImageCache{
private LruCache<String, Bitmap> mCache;
public MyImageCache(){
int maxSize = 8 * 1024 * 1024;//将缓存图片的大小设置为8M
mCache = new LruCache<String,Bitmap>(maxSize){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
};
}
@Override
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
mCache.put(url, bitmap);
}
}
3, NetworkImageView的用法
NetworkImageView是一个自定义控制,它是继承自ImageView的,具备ImageView控件的所有功能,并且在原生的基础之上加入了加载网络图片的功能。NetworkImageView控件的用法分为以下四步:
1)1,创建RequestQueue对象
2)创建ImageLoader对象
3)获取NetworkImageView空间
4)设置加载图片的url
public class NetworkImageViewActivity extends Activity{
private Context mContext = this;
private NetworkImageView mNetworkImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.network_imageview_activity);
//1,创建RequestQueue对象
RequestQueue requestQueue = Volley.newRequestQueue(mContext);
//2,创建ImageLoader对象
ImageLoader imageLoader = new ImageLoader(requestQueue, new MyImageCache());
//3,获取NetworkImageView空间
mNetworkImageView = (NetworkImageView)findViewById(R.id.network_image_view);
//4,设置加载图片的url
mNetworkImageView.setDefaultImageResId(R.drawable.image_default);
mNetworkImageView.setErrorImageResId(R.drawable.image_err);
mNetworkImageView.setImageUrl("http://t12.baidu.com/it/u=4095575894,102452705&fm=32&s=A98AA55F526172A6F6A058E50300A060&w=623&h=799&img.JPEG", imageLoader);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/network_image_view"
android:layout_width="300dip"
android:layout_height="300dip"
android:layout_gravity="center_horizontal"/>
</LinearLayout>