android网络编程 三(Volley)

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);
		}
		
	}

}







 
 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值