您的位置:首页 > 理论基础 > 计算机网络

android网络编程 三(Volley)

2016-01-17 22:27 651 查看
Android系统中主要提供了两种方式来进行HTTP通信,HttpURLConnection和HttpClient,几乎任何项目的代码中我们都能看到两个类的身影,使用率非常高。不过HttpURLConnection和HttpClient的用法还是有些复杂,Android开发团队也是意识到了有必要将HTTP的通信操作再进行简单化,于是在2013年Google I/O大会上推出了一个新的网络通信框架——Volley

Volley除了简单易用之外,在性能方面也进行了大幅度调整,它的设计目标适就是适合进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。

Volley下载地址:

git clone (点击打开链接)http://android.googlesource.com/platform/frameworks/volley

这里提供我上传的jar包:http://download.csdn.net/detail/yabaj/9408577

Volley提供的功能:

JSON,图像等的异步下载;
网络请求的排序(scheduling)
网络请求的优先级处理
缓存
多级别取消请求
和Activity的生命周期的联动(Activity结束时同时取消所有网络请求)

Volley的常用HTTP请求方式:

1.StringRequest

RequestQueue是一个请求队列对象,它可以缓存所有的HTTP请求,然后按照一定的算法并发地发出这些请求。RequestQueue内部的设计就是非常适合高并发的,因此我们不必为每一次HTTP请求都创建一个RequestQueue对象,这是非常浪费资源的,基本上在每一个需要和网络交互的Activity中创建一个RequestQueue对象就足够了,而且其中内置了线程不用我们去写。

示例代码:

public class NetworkActivity extends Activity implements OnClickListener{

private RequestQueue queue = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);

Button bt = (Button) findViewById(R.id.bt_volley_stringrequest);

bt.setOnClickListener(this);

//创建队列
queue = Volley.newRequestQueue(getApplicationContext());
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bt_volley_stringrequest:
// TODO Auto-generated method stub
/*String path = "http://192.168.1.100:8080/TestAndroid/testServlet?name=zhangsan&age=23";
StringRequest request = new StringRequest(Request.Method.GET, path, new Listener<String>() {

@Override
public void onResponse(String arg0) {
// TODO Auto-generated method stub

String s = null;
try {
byte temp[]=arg0.getBytes("iso-8859-1");
s = new String(temp,"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
////打印出服务器传过来的数据
Log.e("onResponse", s);
}
}, new com.android.volley.Response.ErrorListener() {

@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
Log.e("错误onErrorResponse", arg0.toString());
}
});*/
String path = "http://192.168.1.100:8080/TestAndroid/testServlet";
StringRequest request = new StringRequest(Request.Method.POST, path, new Listener<String>() {

@Override
public void onResponse(String arg0) {
// TODO Auto-generated method stub

String s = null;
try {
byte temp[]=arg0.getBytes("iso-8859-1");
s = new String(temp,"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.e("onResponse", s);
}
}, new com.android.volley.Response.ErrorListener() {

@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
Log.e("错误onErrorResponse", arg0.toString());
}
}){
@Override
protected Map<String, String> getParams()
throws AuthFailureError {
// TODO Auto-generated method stub
Map<String, String> map = new HashMap<String, String>();
map.put("name", "张三");
map.put("age", "24");
return map;
}
};
queue.add(request);
break;
default:
break;
}
}
}


get请求结果:



post请求结果:



我们可以看出连接服务器只需一个类StringRequest就解决了问题,是不是很激动。。再看下一个。。

2.JsonRequest

类似于StringRequest,JsonRequest也是继承自Request类的,JsonRequest是一个抽象类。JsonRequest有两个直接的子类JsonObjectRequest和JsonArrayRequest。

示例代码:

这种方式服务器只能向前台传送json格式的数据,(一)的服务器代码需要作如下改动:

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");

System.out.println("进入get方法");

String name = request.getParameter("name");
String age = request.getParameter("age");
System.out.println("name=" + name + ",age=" + age);
PrintWriter writer = response.getWriter();
//		writer.write("Get : name,age send 成功");
String json = "{'info':'Get','content':'name,age send 成功'}";//json字符串
writer.write(json);
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");

System.out.println("进入post方法");

String name = request.getParameter("name");
String age = request.getParameter("age");
System.out.println("name=" + name + ",age=" + age);
PrintWriter writer = response.getWriter();
//		writer.write("Post : name,age send 成功");
String json = "{'info':'Post','content':'name,age send 成功'}";<span style="font-family: Arial, Helvetica, sans-serif;">//json字符串</span>
writer.write(json);
}


android端代码:

POST请求时,JsonObjectRequest的构造方法参数里不能直接传JsonObject对象进去,因为我使用的apache tomcat服务器只支持传入键值对格式参数的方式(如name='zhangsan'&age=23),而不支持json格式。所以需要重写Request类中的parseNetworkResponse方法,非常麻烦,这种情况下不建议使用。

public class NetworkActivity extends Activity implements OnClickListener{

private RequestQueue queue = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);

Button bt = (Button) findViewById(R.id.bt_volley_jsonrequest);

bt.setOnClickListener(this);

//创建队列
queue = Volley.newRequestQueue(getApplicationContext());
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bt_volley_jsonrequest:
//get请求
/*String path = "http://192.168.1.100:8080/TestAndroid/testServlet?name=zhangsan&age=23";
//这里是get请求,不用在这里传参,JsonRequest为null
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, path, null, new Listener<JSONObject>() {

@Override
public void onResponse(JSONObject arg0) {
// TODO Auto-generated method stub
String s = null;
try {
byte temp[]=arg0.toString().getBytes("iso-8859-1");
s = new String(temp,"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
////打印出服务器传过来的数据
Log.e("onResponse", s);
}
}, new com.android.volley.Response.ErrorListener() {

@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
Log.e("错误onErrorResponse", arg0.toString());
}
});*/

//post请求
String path = "http://192.168.1.100:8080/TestAndroid/testServlet";

Map<String, String> map = new HashMap<String, String>();
map.put("name", "张三");
map.put("age", "24");

NormalPostRequest request = new NormalPostRequest(path, new Listener<JSONObject>() {

@Override
public void onResponse(JSONObject arg0) {
// TODO Auto-generated method stub
String s = null;
try {
byte temp[]=arg0.toString().getBytes("iso-8859-1");
s = new String(temp,"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
////打印出服务器传过来的数据
Log.e("onResponse", s);
}
}, new com.android.volley.Response.ErrorListener() {

@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
Log.e("错误onErrorResponse", arg0.toString());
}
}, map);

queue.add(request);
break;
default:
break;
}
}

private class NormalPostRequest extends Request<JSONObject> {
private Map<String, String> mMap;
private Listener<JSONObject> mListener;
public NormalPostRequest(String url, Listener<JSONObject> listener,ErrorListener errorListener, Map<String, String> map) {
super(Request.Method.POST, url, errorListener);

mListener = listener;
mMap = map;
}

//mMap是已经按照前面的方式,设置了参数的实例
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return mMap;
}

//此处因为response返回值需要json数据,和JsonObjectRequest类一样即可
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,HttpHeaderParser.parseCharset(response.headers));

return Response.success(new JSONObject(jsonString),HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
@Override
protected void deliverResponse(JSONObject response) {
mListener.onResponse(response);
}
}

}


get请求运行结果:



post请求运行结果:



3.ImageRequest

用于网络图片加载。

示例代码:

public class NetworkActivity extends Activity implements OnClickListener{

private RequestQueue queue = null;
private ImageView imageView = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);

Button bt = (Button) findViewById(R.id.bt_volley_imagerequest);

bt.setOnClickListener(this);

imageView = (ImageView) findViewById(R.id.my_image);

//创建队列
queue = Volley.newRequestQueue(getApplicationContext());
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bt_volley_imagerequest:
//网络上的图片下载地址,也可以换成自己的服务器地址
String path = "http://image.baidu.com/search/down?tn=download&word=download&ie=utf8&fr=detail&url=http%3A%2F%2Fwww.th7.cn%2Ffeizhuliu%2FUploadFiles_2544%2F201010%2F2010100513025822.jpg&thumburl=http%3A%2F%2Fimg5.imgtn.bdimg.com%2Fit%2Fu%3D3866172907%2C1449770762%26fm%3D206%26gp%3D0.jpg";
// 参数解释
// 第一个:图片下载路径
// 第二个:图片请求成功的回调,在这里把返回的Bitmap参数设置到ImageView中
// 第三、四个:指定图片的最大宽度和最大高度,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,指定成0的话,不管图片多大都不会进行压缩
// 第五个:指定图片的颜色属性,Config.ARGB_8888:最优的颜色,每个图片像素占四个字节;Config.RGB_565:每个图片像素占两个字节
// 第六个:图片请求失败的回调,这里当我们请求失败时在ImageView显示一张默认图片
ImageRequest request = new ImageRequest(path, new Listener<Bitmap>() {

@Override
public void onResponse(Bitmap bitmap) {
// TODO Auto-generated method stub
imageView.setImageBitmap(bitmap);
}
}, 0, 0, Config.RGB_565, new ErrorListener() {

@Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
Log.e("错误回调", error.toString());
}
});

queue.add(request);
break;
default:
break;
}
}

}


4.ImageLoader

ImageLoader也可用于图片加载,并且它的内部也是呀ImageRequest来实现的,不过ImageLoader要比ImageRequest更加高效,因为它不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。

示例代码:

●●这里是无缓存的代码:

public class NetworkActivity extends Activity implements OnClickListener{

private RequestQueue queue = null;
private ImageView imageView = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);

Button bt = (Button) findViewById(R.id.bt_volley_imageloader);

bt.setOnClickListener(this);

imageView = (ImageView) findViewById(R.id.my_image);

//创建队列
queue = Volley.newRequestQueue(getApplicationContext());
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bt_volley_imageloader:
String path = "http://192.168.0.141:8080/TestAndroid/image/pic01.jpg";
//创建ImageLoader加载器
//无缓存
ImageLoader imageLoader = new ImageLoader(queue, new ImageCache() {

@Override
public void putBitmap(String arg0, Bitmap arg1) {
// TODO Auto-generated method stub

}

@Override
public Bitmap getBitmap(String arg0) {
// TODO Auto-generated method stub
return null;
}
});

//获取ImageListener监听器对象
ImageListener imageListener = ImageLoader.getImageListener(imageView, R.drawable.bg01, R.drawable.ic_launcher);

//访问图片地址
imageLoader.get(path, imageListener, 400, 400);
break;
default:
break;
}
}

}


●●这里是有缓存的代码(需要自己写一个缓存的类,实现ImageCache接口):

public class NetworkActivity extends Activity implements OnClickListener{

private RequestQueue queue = null;
private ImageView imageView = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);

Button bt = (Button) findViewById(R.id.bt_volley_imageloader);

bt.setOnClickListener(this);

imageView = (ImageView) findViewById(R.id.my_image);

//创建队列
queue = Volley.newRequestQueue(getApplicationContext());
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bt_volley_imageloader:
String path = "http://192.168.0.141:8080/TestAndroid/image/pic01.jpg";
//创建ImageLoader加载器
//有缓存
ImageLoader imageLoader = new ImageLoader(queue, new MyImageCache());
//获取ImageListener监听器对象
ImageListener imageListener = ImageLoader.getImageListener(imageView, R.drawable.bg01, R.drawable.ic_launcher);

//访问图片地址
imageLoader.get(path, imageListener, 400, 400);
break;
default:
break;
}
}

/*
* 这里是二级缓存,保存在内存里,程序关闭自动清空
*/
private class MyImageCache implements ImageCache{

private LruCache<String, Bitmap> lruCache = null;

public MyImageCache() {
super();
int maxSize = 10 * 1024 * 1024;
//创建缓存容器,缓存Bitmap
this.lruCache = new LruCache<String, Bitmap>(maxSize){
/*
* 计算每次缓存一个bitmap的大小
* @see android.util.LruCache#sizeOf(java.lang.Object, java.lang.Object)
*/
@Override
protected int sizeOf(String key, Bitmap value) {
// TODO Auto-generated method stub
//计算每个位图的字节大小
return value.getRowBytes() * value.getHeight();
}
};
}

/*
* 从缓存中取出bitmap对象
* @see com.android.volley.toolbox.ImageLoader.ImageCache#getBitmap(java.lang.String)
*/
@Override
public Bitmap getBitmap(String arg0) {
// TODO Auto-generated method stub
Log.e("getBitmap---arg0", arg0);
return lruCache.get(arg0);
}

/*
* 将下载下来的位图对象放入缓存中
* @see com.android.volley.toolbox.ImageLoader.ImageCache#putBitmap(java.lang.String, android.graphics.Bitmap)
*/
@Override
public void putBitmap(String arg0, Bitmap bitmap) {
// TODO Auto-generated method stub
lruCache.put(arg0, bitmap);
}

}

}


5.NetworkImageView

这是第三种加载网络图片的方式,NetworkImageView是一个自定义控件,它是继承自ImageView的,具备ImageView控件所有功能,且在原生的基础上加入了加载网络图片的功能。这种方法比前两种加载图片的方式更加简单。

●●添加布局文件:

<com.android.volley.toolbox.NetworkImageView
android:layout_width="400dp"
android:layout_height="400dp"
android:scaleType="fitXY"
android:background="@android:color/holo_blue_light"
android:id="@+id/my_network_image">
●●示例代码:

public class NetworkActivity extends Activity implements OnClickListener{

private RequestQueue queue = null;
private NetworkImageView networkImageView = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);

Button bt1 = (Button) findViewById(R.id.bt_volley_imagerequest);
bt1.setOnClickListener(this);

networkImageView = (NetworkImageView) findViewById(R.id.my_network_image);

//创建队列
queue = Volley.newRequestQueue(getApplicationContext());
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bt_volley_networkimageview:
String path = "http://image.baidu.com/search/down?tn=download&ipn=dwnl&word=download&ie=utf8&fr=result&url=http%3A%2F%2Fa.hiphotos.baidu.com%2Fzhidao%2Fpic%2Fitem%2Fc2cec3fdfc039245c62b6f018594a4c27d1e2525.jpg&thumburl=http%3A%2F%2Fimg1.imgtn.bdimg.com%2Fit%2Fu%3D2872232886%2C2936175233%26fm%3D206%26gp%3D0.jpg";
networkImageView.setDefaultImageResId(R.drawable.bg01);
networkImageView.setErrorImageResId(R.drawable.ic_launcher);

ImageLoader imageLoader = new ImageLoader(queue, new MyImageCache());

//下载图片
networkImageView.setImageUrl(path, imageLoader);
break;

default:
break;
}
}

/*
* 这里是二级缓存,保存在内存里,程序关闭自动清空
*/
private class MyImageCache implements ImageCache{

private LruCache<String, Bitmap> lruCache = null;

public MyImageCache() {
super();
int maxSize = 10 * 1024 * 1024;
//创建缓存容器,缓存Bitmap
this.lruCache = new LruCache<String, Bitmap>(maxSize){
/*
* 计算每次缓存一个bitmap的大小
* @see android.util.LruCache#sizeOf(java.lang.Object, java.lang.Object)
*/
@Override
protected int sizeOf(String key, Bitmap value) {
// TODO Auto-generated method stub
//计算每个位图的字节大小
return value.getRowBytes() * value.getHeight();
}
};
}

/*
* 从缓存中取出bitmap对象
* @see com.android.volley.toolbox.ImageLoader.ImageCache#getBitmap(java.lang.String)
*/
@Override
public Bitmap getBitmap(String arg0) {
// TODO Auto-generated method stub
Log.e("getBitmap---arg0", arg0);
return lruCache.get(arg0);
}

/*
* 将下载下来的位图对象放入缓存中
* @see com.android.volley.toolbox.ImageLoader.ImageCache#putBitmap(java.lang.String, android.graphics.Bitmap)
*/
@Override
public void putBitmap(String arg0, Bitmap bitmap) {
// TODO Auto-generated method stub
lruCache.put(arg0, bitmap);
}

}

}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: