现在开发app,可以说离不开网络操作,今天给大家介绍一下android网络框架volley的使用方法。
Volley主页 https://android.googlesource.com/platform/frameworks/volley
Github地址 https://github.com/mcxiaoke/android-volley
Volley:2013年Google I/O大会上推出的一个新的Android网络通信框架,能使网络通信更快,更简单,更健壮。
功能:
Json,图像等的异步下载
网络请求的排序(scheduling)
网络请求的优先级处理
缓存
多级别取消请求
和Activity生命周期联动(Activity结束时同时取消所有请求)
使用volley: compile 'com.mcxiaoke.volley:library:1.0.19'
StringRequest使用方法:
演示:通过StringRequest发送一个get请求
private void getStringRequest() {
String url="http://api.k780.com:88/?app=phone.get&phone=13800138000&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json";
RequestQueue queue= Volley.newRequestQueue(this);
StringRequest request=new StringRequest(url, new Response.Listener() {
@Override
public void onResponse(String s) {
Log.e("success",s);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
}
});
queue.add(request);
}
演示:通过StringRequest发送一个post请求
private void postStringRequest() {
String url="http://api.k780.com:88/?app=phone.get";
RequestQueue queue=Volley.newRequestQueue(this);
StringRequest request=new StringRequest(Request.Method.POST, url, new Response.Listener() {
@Override
public void onResponse(String s) {
Log.e("sucess",s);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
}
}){
@Override
protected Map getParams() throws AuthFailureError {
Map map=new HashMap<>();
map.put("phone","13800138000");
map.put("appkey", "10003");
map.put("sign", "b59bc3ef6191eb9f747dd4e83c99f2a4");
map.put("format", "json");
map.put("idcard", "110101199001011114");
return map;
}
};
queue.add(request);
}
通过上述代码,我们可以总结出,StringRequest可以发送get和post请求,但是服务器返回的数据以String类型进行接收。
通过StringRequest发送请求一般需要以下三步:
1.创建一个请求队列RequestQueue
2.创建StringRequest对象
3.将请求对象添加到请求队列中
JsonRequest使用方法:
演示:通过JsonRequest发送一个get请求
private void getJsonRequest() {
String url="http://api.k780.com:88/?app=phone.get&phone=13800138000&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json";
RequestQueue queue= Volley.newRequestQueue(this);
JsonObjectRequest request=new JsonObjectRequest(url, new Response.Listener() {
@Override
public void onResponse(JSONObject jsonObject) {
Log.e("success",jsonObject.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
}
});
queue.add(request);
}
private void postJsonRequest() {
String url="http://api.k780.com:88/?app=phone.get";
RequestQueue queue=Volley.newRequestQueue(this);
JsonObjectRequest request=new JsonObjectRequest(Request.Method.POST, url, new Response.Listener() {
@Override
public void onResponse(JSONObject jsonObject) {
Log.e("success",jsonObject.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
}
}){
@Override
protected Map getParams() throws AuthFailureError {
Map map=new HashMap<>();
map.put("phone","13800138000");
map.put("appkey", "10003");
map.put("sign", "b59bc3ef6191eb9f747dd4e83c99f2a4");
map.put("format", "json");
map.put("idcard", "110101199001011114");
return map;
}
};
queue.add(request);
}
通过以上分析,可以发现,StringRequest和JsonObjectRequest用法基本一样,只是接收的数据类型不一样。
同理,JsonArrayRequest方法和上面的用法也差不多,这里不做过多介绍。
封装Volley:
具体实现功能如下:
发送get请求
发送post请求
加载网络图片
上传图片
Volley管理的类:
/**
* 管理类
* @author Yan
*/
public class MyVolley {
private static final String TAG="MyVolley";
private static MyVolley instance;
//请求队列
private static RequestQueue mRequestQueue;
//创建ImageLoader
private static ImageLoader mImageLoader;
//默认分配最大空间的几分之几
private final static int RATE=8;
public MyVolley(Context context){
//初始化请求队列(默认创建5个线程)
mRequestQueue=Volley.newRequestQueue(context);
//获取ActivityManager管理者
ActivityManager manager=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int maxSize=manager.getMemoryClass()/RATE;
//初始化ImageLoader对象
mImageLoader=new ImageLoader(mRequestQueue, new BitmapLruCache(1024*1024*maxSize));
Log.e(TAG, "MyVolley初始化完成");
}
/**
* Volley的初始化操作,使用volley前必须调用此方法
*/
public static void init(Context context){
if(instance==null){
instance=new MyVolley(context);
}
}
/**
* 获取消息队列
*/
public static RequestQueue getRequestQueue(){
throwIfNotInit();
return mRequestQueue;
}
/**
* 获取ImageLoader
*/
public static ImageLoader getImageLoader(){
throwIfNotInit();
return mImageLoader;
}
/**
* 加入请求队列
*/
public static void addRequest(Request> request){
getRequestQueue().add(request);
}
/**
* 加载网络图片
*/
public static void getImage(String requestUrl, ImageView imageView) {
getImage(requestUrl, imageView, 0, 0);
}
/**
* 加载网络图片
*
*/
public static void getImage(String requestUrl, ImageView imageView,
int defaultImageResId, int errorImageResId) {
getImage(requestUrl, imageView, defaultImageResId, errorImageResId, 0,
0);
}
/**
* 加载网络图片
*
*/
public static void getImage(String requestUrl, ImageView imageView,
int defaultImageResId, int errorImageResId, int maxWidth,
int maxHeight) {
imageView.setTag(requestUrl);
try {
getImageLoader().get(
requestUrl,
ImageListenerFactory.getImageListener(imageView,
defaultImageResId, errorImageResId), maxWidth,
maxHeight);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 检查是否完成初始化
*/
private static void throwIfNotInit() {
if (instance == null) {
throw new IllegalStateException("MyVolley尚未初始化,在使用前应该执行init()");
}
}
}
通过以上代码,主要提供了下面几个方法:
1.在构造方法中,初始化一个全局的请求队列RequestQueue,初始化了一个ImageLoader。
2.获取消息队列
3.获取ImageLoader对象
4.将请求加入到消息队列中
5.加载图片
注意:使用MyVolley时,一定要在应用的全局的Application中进行初始化 MyVolley.init(getApplicationContext());
加载图片中涉及到的2个缓存类如下:
/**
* 图片缓存类(Lru算法)
* @author Yan
*
*/
public class BitmapLruCache extends LruCache implements ImageCache{
private static final String TAG="BitmapLruCache";
//图片缓存的软引用
private BitmapSoftRefCache softRefCache;
public BitmapLruCache(int maxSize) {
super(maxSize);
//初始化BitmapSoftRefCache
softRefCache=new BitmapSoftRefCache();
}
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight();
}
@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue,
Bitmap newValue) {
if(evicted){
//将bitmap添加到软引用的缓存中
softRefCache.putBitmap(key, oldValue);
}
}
/**
* 从缓存中获取图片
*/
@Override
public Bitmap getBitmap(String url) {
Bitmap bitmap=get(url);
if(bitmap==null){
//从软引用缓存中获取
bitmap=softRefCache.getBitmap(url);
}
return bitmap;
}
/**
* 将图片放入到缓存中
*/
@Override
public void putBitmap(String url, Bitmap bitmap) {
put(url, bitmap);
}
}
/**
* 图片缓存管理类(软引用)
* @author Yan
*
*/
public class BitmapSoftRefCache implements ImageCache {
private static final String TAG="BitmapSoftRefCache";
//创建一个集合保存Bitmap
private LinkedHashMap> map;
public BitmapSoftRefCache(){
map=new LinkedHashMap<>();
}
/**
* 根据图片url从缓存中拿出bitmap
*/
@Override
public Bitmap getBitmap(String url) {
Bitmap bitmap=null;
SoftReference softRef=map.get(url);
if(softRef!=null){
bitmap=softRef.get();
if(bitmap==null){
//从集合中移除
map.remove(url);
}
}
return null;
}
/**
* 把图片放进缓存中
*/
@Override
public void putBitmap(String url, Bitmap bitmap) {
SoftReference softRef=new SoftReference(bitmap);
map.put(url, softRef);
}
}
/**
* 图片加载状态监听
* @author Yan
*
*/
public class ImageListenerFactory {
private static final String TAG="ImageListenerFactory";
public static ImageListener getImageListener(final ImageView view,
final int defaultImageResId, final int errorImageResId){
return new ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
if(errorImageResId!=0){
view.setImageResource(errorImageResId);
}
}
@Override
public void onResponse(ImageContainer response, boolean isImmediate) {
if(response.getBitmap()!=null){
if(view.getTag().toString().equals(response.getRequestUrl())){
view.setImageBitmap(response.getBitmap());
}
}
else if(defaultImageResId!=0){
view.setImageResource(defaultImageResId);
}
}
};
}
}
/**
* 返回成功监听(自定义处理逻辑)
* @author Yan
*/
public abstract class MyReponseListener implements Response.Listener {
@Override
public void onResponse(BaseVO arg0) {
onMyResponse(arg0);
}
public boolean onMyResponse(BaseVO t) {
// DialogMaker.closeProgressDialog();
// 自定义处理逻辑
...
return true;
}
}
/**
* 自定义返回错误信息监听
*
* @author Yan
*
*/
public abstract class MyErrorListener implements ErrorListener {
public void onErrorResponse(VolleyError error) {
//自定义同意错误逻辑处理
...
}
}
下面提供一个请求服务器返回数据后封装成对象的一个GsonRequest:
public class GsonRequest extends Request{
private static final String TAG="GsonRequest";
//超时时间,默认10秒
private int defaultHttpTimeOut=10*1000;
//回调监听
private Listener listener;
//返回类型
private Type type;
//请求参数
private Map methodBody;
/**
* get请求
*
* @param url
* @param type
* @param listener
* @param errorListener
*/
public GsonRequest(String url, Type type, Listener listener,
ErrorListener errorListener) {
super(Method.GET, url, errorListener);
// 不启用缓存(默认是true)
setShouldCache(false);
this.type = type;
this.listener = listener;
// 设置重连策略
this.setRetryPolicy(new DefaultRetryPolicy(defaultHttpTimeOut,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
/**
* post请求
*
* @param methodName
* @param methodBoby
* @param type
* @param listener
* @param errorListener
*/
public GsonRequest(String url, Map methodBoby, Type type,
Listener listener, ErrorListener errorListener) {
super(Method.POST, url, errorListener);
this.methodBody = methodBoby;
this.listener = listener;
this.type = type;
// 不启用缓存
setShouldCache(false);
// 设置重连策略
this.setRetryPolicy(new DefaultRetryPolicy(defaultHttpTimeOut,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
/**
* 设置请求参数
*/
@Override
protected Map getParams() throws AuthFailureError {
if(methodBody==null){
return super.getParams();
}
//创建一个集合,保存请求参数
Map map=new LinkedHashMap<>();
//----此处可以添加多个通用参数
//map.put(key,value);
//------
//------
//遍历集合
Iterator> iter=methodBody.entrySet().iterator();
while(iter.hasNext()){
Entry entry=iter.next();
map.put(entry.getKey(), entry.getValue());
}
return map;
}
/**
* 将服务器返回的原生字节内容进行转换
*/
@Override
protected Response parseNetworkResponse(NetworkResponse response) {
try {
// 获取返回的数据(在 Content-Type首部中获取编码集,如果没有找到,默认返回 ISO-8859-1)
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(parseNetworkResponseDelegate(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}
/**
* 将服务器返回的内容用gson进行封装
*/
private BaseVO parseNetworkResponseDelegate(String jsonString) {
return new Gson().fromJson(jsonString, type);
}
/**
* 将解析后的数据进行回调
*/
@Override
protected void deliverResponse(BaseVO arg0) {
listener.onResponse(arg0);
}
}
**
* 服务器以XML格式返回数据
* @author Yan
*/
public class XMLRequest extends Request{
private Listener mListener;
public XMLRequest(int method, String url, Listener listener,
ErrorListener errorListener){
super(method, url, errorListener);
//不启用缓存
setShouldCache(false);
mListener=listener;
}
public XMLRequest(String url, Listener listener, ErrorListener errorListener) {
this(Method.GET, url, listener, errorListener);
}
/**
* 解析服务器返回的数据
*/
@Override
protected Response parseNetworkResponse(
NetworkResponse response) {
try {
String xmlString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
//创建解析工厂
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//获取解析器
XmlPullParser xmlPullParser = factory.newPullParser();
//设置解析数据
xmlPullParser.setInput(new StringReader(xmlString));
return Response.success(xmlPullParser, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (XmlPullParserException e) {
return Response.error(new ParseError(e));
}
}
/**
* 分发结果
*/
@Override
protected void deliverResponse(XmlPullParser response) {
mListener.onResponse(response);
}
}
public class PostUploadRequest extends Request{
/**
* 正确数据的时候回掉用
*/
private Listener mListener ;
/*请求 数据通过参数的形式传入*/
private List mListItem ;
private String BOUNDARY = "--------------520-13-14"; //数据分隔线
private String MULTIPART_FORM_DATA = "multipart/form-data";
public PostUploadRequest(String url, List listItem, Listener listener,
ErrorListener errorListener) {
super(Method.POST, url, errorListener);
this.mListener = listener ;
setShouldCache(false);
mListItem = listItem ;
//设置请求的响应事件,因为文件上传需要较长的时间,所以在这里加大了,设为10秒
setRetryPolicy(new DefaultRetryPolicy(10*1000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
/**
* 这里开始解析数据
* @param response Response from the network
* @return
*/
@Override
protected Response parseNetworkResponse(NetworkResponse response) {
try {
String mString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(mString,
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
/**
* 回调正确的数据
* @param response The parsed response returned by
*/
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
@Override
public byte[] getBody() throws AuthFailureError {
if (mListItem == null||mListItem.size() == 0){
return super.getBody() ;
}
ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
int N = mListItem.size() ;
for (int i = 0; i < N ;i++){
FormImage formImage = mListItem.get(i) ;
StringBuffer sb= new StringBuffer() ;
/*第一行*/
//`"--" + BOUNDARY + "\r\n"`
sb.append("--"+BOUNDARY);
sb.append("\r\n") ;
/*第二行*/
//Content-Disposition: form-data; name="参数的名称"; filename="上传的文件名" + "\r\n"
sb.append("Content-Disposition: form-data;");
sb.append(" name=\"");
sb.append(formImage.getName()) ;
sb.append("\"") ;
sb.append("; filename=\"") ;
sb.append(formImage.getFileName()) ;
sb.append("\"");
sb.append("\r\n") ;
/*第三行*/
//Content-Type: 文件的 mime 类型 + "\r\n"
sb.append("Content-Type: ");
sb.append(formImage.getMime()) ;
sb.append("\r\n") ;
/*第四行*/
//"\r\n"
sb.append("\r\n") ;
try {
bos.write(sb.toString().getBytes("utf-8"));
/*第五行*/
//文件的二进制数据 + "\r\n"
bos.write(formImage.getValue());
bos.write("\r\n".getBytes("utf-8"));
} catch (IOException e) {
e.printStackTrace();
}
}
/*结尾行*/
//`"--" + BOUNDARY + "--" + "\r\n"`
String endLine = "--" + BOUNDARY + "--" + "\r\n" ;
try {
bos.write(endLine.toString().getBytes("utf-8"));
} catch (IOException e) {
e.printStackTrace();
}
return bos.toByteArray();
}
//Content-Type: multipart/form-data; boundary=----------8888888888888
@Override
public String getBodyContentType() {
return MULTIPART_FORM_DATA+"; boundary="+BOUNDARY;
}
}
public class FormImage {
//参数的名称
private String name ;
//文件名
private String fileName ;
//文件的mine
private String mime ;
//需要上传的文件
private File file ;
public FormImage() {
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public String getMime() {
return mime;
}
public void setMime(String mime) {
this.mime = mime;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//对文件进行二进制转换
public byte[] getValue() {
byte[] buffer = null;
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
private void getMyVolley() {
String url="http://api.k780.com:88/?app=idcard.get&idcard=110101199001011114&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json";
GsonRequest request=new GsonRequest(url, PersonInfoBean.class, new MyReponseListener() {
@Override
public void onResponse(BaseVO t) {
super.onResponse(t);
PersonInfoBean bean=(PersonInfoBean) t;
Log.e("success", bean.toString());
}
}, new MyErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
super.onErrorResponse(error);
}
});
MyVolley.addRequest(request);
}
private void postMyVolley() {
String url="http://api.k780.com:88/?app=idcard.get";
Map map=new HashMap<>();
map.put("appkey", "10003");
map.put("sign", "b59bc3ef6191eb9f747dd4e83c99f2a4");
map.put("format", "json");
map.put("idcard", "110101199001011114");
GsonRequest request=new GsonRequest(url, map, PersonInfoBean.class, new MyReponseListener() {
@Override
public void onResponse(BaseVO vo) {
super.onResponse(vo);
PersonInfoBean bean=(PersonInfoBean) vo;
Log.e("sucess", bean.toString());
}
}, new MyErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
super.onErrorResponse(error);
}
});
MyVolley.addRequest(request);
}
//上传文件路径
String url="http://192.168.1.107:8080/FileUpload/FileServlet";
List list=new ArrayList<>();
String path1= Environment.getExternalStorageDirectory().getPath()+File.separator+"ss.png";
String path2= Environment.getExternalStorageDirectory().getPath()+File.separator+"ic_launcher.png";
File file1=new File(path1);
File file2=new File(path2);
FormImage f1=new FormImage();
f1.setFile(file1);
f1.setFileName("t1");
f1.setName("file1");
f1.setMime("image/png");
list.add(f1);
FormImage f2=new FormImage();
f2.setFile(file2);
f2.setFileName("t2");
f2.setName("file2");
f2.setMime("image/png");
list.add(f2);
PostUploadRequest request=new PostUploadRequest(url, list, new Response.Listener() {
@Override
public void onResponse(String s) {
Log.e("success",s);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
}
});
MyVolley.addRequest(request);
}
private void getXml() {
String url="http://flash.weather.com.cn/wmaps/xml/china.xml";
XMLRequest request=new XMLRequest( url, new Response.Listener() {
@Override
public void onResponse(XmlPullParser xmlPullParser) {
try {
int eventType = xmlPullParser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG:
String nodeName = xmlPullParser.getName();
if ("city".equals(nodeName)) {
String pName = xmlPullParser.getAttributeValue(0);
Log.e("TAG", "city is " + pName);
}
break;
}
eventType = xmlPullParser.next();
}
}catch(Exception e){
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
}
});
MyVolley.addRequest(request);
}
public class MyAdapter extends BaseAdapter{
private Context context;
private List list;
private LayoutInflater mInflater;
public ViewHolder holder;
public MyAdapter(Context context, List list) {
this.context = context;
this.list = list;
this.mInflater=LayoutInflater.from(context);
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
holder=null;
if(convertView==null){
convertView=mInflater.inflate(R.layout.itemone, null);
holder=new ViewHolder();
holder.iv_image=(ImageView) convertView.findViewById(R.id.iv_image);
holder.tv_name=(TextView) convertView.findViewById(R.id.tv_name);
convertView.setTag(holder);
}
else{
holder=(ViewHolder) convertView.getTag();
}
Person bean=list.get(position);
holder.tv_name.setText(bean.getName());
MyVolley.getImage(bean.getImgUrl(), holder.iv_image, R.mipmap.ic_launcher, R.mipmap.ic_launcher,150,150);
return convertView;
}
class ViewHolder{
private TextView tv_name;
private ImageView iv_image;
}
}