Volley是Ficus Kirpatrick在Gooogle I/O 2013发布的一个处理和缓存网络请求的库,能使网络通信更快,更简单,更健壮。
Volley名称的由来: a burst or emission of many things or a large amount at once。
该框架适用于大部分app应用,其特点在与方便频繁与网络交互,如:图片加载,json解析等。
NetUtil.java 类 ,一句话解析Json,一句话加载网络图片
在 MainActivity.java中使用:
Volley名称的由来: a burst or emission of many things or a large amount at once。
该框架适用于大部分app应用,其特点在与方便频繁与网络交互,如:图片加载,json解析等。
笔者对其进行封装,使其在项目中能更加方便和实用,大大开发效率。使之能一句话加载网络图片,一句话解析json 。
我们来看一下源码 volley.java
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.volley.toolbox;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.http.AndroidHttpClient;
import android.os.Build;
import com.android.volley.Network;
import com.android.volley.RequestQueue;
import java.io.File;
public class Volley {
/** Default on-disk cache directory. */
private static final String DEFAULT_CACHE_DIR = "volley";
/**
* Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.
*
* @param context A {@link Context} to use for creating the cache dir.
* @param stack An {@link HttpStack} to use for the network, or null for default.
* @return A started {@link RequestQueue} instance.
*/
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
String userAgent = "volley/0";
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
userAgent = packageName + "/" + info.versionCode;
} catch (NameNotFoundException e) {
}
if (stack == null) {
//用HttpUrlConnection 处理http请求
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.用HttpClient处理网络请求
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
//构建一个字节池
Network network = new BasicNetwork(stack);
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
/**
* Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.
*
* @param context A {@link Context} to use for creating the cache dir.
* @return A started {@link RequestQueue} instance.
*/
public static RequestQueue newRequestQueue(Context context) {
return newRequestQueue(context, null);
}
}
package com.cn.framework.net;
import android.content.Context;
import android.widget.ImageView;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageCache;
import com.android.volley.toolbox.ImageLoader.ImageContainer;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import com.android.volley.toolbox.Volley;
/**
* 使用NetContext来访问网络,NetContext底部使用Volley作为通信框架
*/
public class NetContext {
/** 上下文 */
private Context context;
/** 图片请求队列 */
private RequestQueue imageRequestQueue;
/** json请求队列 */
private RequestQueue jsonRequestQueue;
/** 图片ImageLoader */
private ImageLoader imageLoader;
/** 图片以及缓存LRU */
private ImageCache imageCache;
/** LRU缓存的数量,为了防止内存溢出,一般不要超过60 */
private static final int LRU_CACHE_SIZE = 20;
private static NetContext instance = null;
/**
* 构造函数
*
* @param context android应用上下文
*/
private NetContext(Context context){
this.context = context;
this.jsonRequestQueue = Volley.newRequestQueue(context);
this.imageRequestQueue = Volley.newRequestQueue(context);
this.imageCache = new BitmapCache(LRU_CACHE_SIZE);
this.imageLoader = new ImageLoader(imageRequestQueue, imageCache);
}
/**
* 单例模式
*
* @param context
* @return NetUtil
*/
public static NetContext getInstance(Context context){
if (instance == null) {
synchronized (NetContext.class) {
if (instance == null) {
instance = new NetContext(context);
}
}
}
return instance;
}
/**
* 得到图片加载器
*
* @return ImageLoader
*/
public ImageLoader getImageLoader() {
return imageLoader;
}
/**
* 得到json的请求队列
* @return RequestQueue
*/
public RequestQueue getJsonRequestQueue() {
return jsonRequestQueue;
}
}
NetUtil.java 类 ,一句话解析Json,一句话加载网络图片
package com.cn.framework.util;
import org.json.JSONArray;
import org.json.JSONObject;
import android.content.Context;
import android.widget.ImageView;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageContainer;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.kuaidian.framework.net.NetContext;
public class NetUtil {
/**
* 防止工具类被实例化
*/
private NetUtil(){
throw new AssertionError();
}
/**
* 加载图片
*
* @param context android应用上下文
* @param imageUrl 请求的图片url
* @param view 展示图片的view
* @param defaultImageResId 加载过程中的默认图片资源Id,如果没有则为0
* @param errorImageResId 加载过程中的错误图片资源Id,如果没有则为0
* @return ImageContainer 图片请求和结果
*/
public static ImageContainer loadImage(Context context, String imageUrl, ImageView view, int defaultImageResId, int errorImageResId){
NetContext netContext = NetContext.getInstance(context);
ImageListener imgListener = ImageLoader.getImageListener(view, defaultImageResId, errorImageResId);
return netContext.getImageLoader().get(imageUrl, imgListener);
}
/**
* 以GET或者POST方式发送jsonObjectRequest
*
* @param context android应用上下文
* @param requestUrl 请求的Url
* @param requestParameter 请求的参数,如果为null,则使用GET方法调用,否则使用POST方法调用
* @param listener 正确返回之后的lisenter
* @param errorListener 错误返回的lisenter
*/
public static void sendJsonObjectRequest(Context context, String requestUrl, JSONObject requestParameter, Listener<JSONObject> listener,
ErrorListener errorListener){
JsonObjectRequest request = new JsonObjectRequest(requestUrl, requestParameter, listener, errorListener);
NetContext netContext = NetContext.getInstance(context);
netContext.getJsonRequestQueue().add(request);
}
/**
* 以GET方式发送jsonArrayRequest
*
* @param context android应用上下文
* @param requestUrl 请求的Url
* @param listener 正确返回之后的lisenter
* @param errorListener 错误返回的lisenter
*/
public static void sendJsonArrayRequest(Context context, String requestUrl, Listener<JSONArray> listener,
ErrorListener errorListener){
JsonArrayRequest request = new JsonArrayRequest(requestUrl,listener, errorListener);
NetContext netContext = NetContext.getInstance(context);
netContext.getJsonRequestQueue().add(request);
}
}
Json解析接口 JsonParserInterface.java
package com.cn.framework.jsonparseinterface;
import org.json.JSONObject;
/**
* jsonResonse的解析接口
*/
public interface JsonParserInterface<T> {
/**
* @param result 返回的结果
* @param response 网络传递进来的response
*/
void parseJson(T result,JSONObject response);
}
package com.cn.framework.jsonparseimpl;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import com.kuaidian.framework.entity.Paper;
import com.kuaidian.framework.jsonparseinterface.JsonParserInterface;
public class PaperParser implements JsonParserInterface<List<Paper>> {
private static PaperParser instance = null;
private PaperParser(){}
public synchronized static PaperParser getInstance(){
if (instance == null) {
instance = new PaperParser();
}
return instance;
}
@Override
public void parseJson(List<Paper> list, JSONObject response) {
try {
JSONArray jsonArray = (JSONArray) response.get("data");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = (JSONObject) jsonArray.get(i);
int id = object.getInt("id");
String smallPic = object.getString("smallPic");
String title = object.getString("layoutpage");
String bigPic = object.getString("bigPic");
Paper newspaper = new Paper();
newspaper.setId(id);
newspaper.setSmallPic(smallPic);
newspaper.setLayoutpage(title);
newspaper.setQi(periodId);
newspaper.setBigPic(bigPic);
list.add(newspaper);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
解析Json时所需要用到的实体类 Paper.java
package com.cn.framework.entity;
import java.util.Date;
public class Paper {
private int id;
private Date date;
private String bigPic;
private String smallPic;
private String bm;
private String layoutpage;
public Paper() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getBigPic() {
return bigPic;
}
public void setBigPic(String bigPic) {
this.bigPic = bigPic;
}
public String getSmallPic() {
return smallPic;
}
public void setSmallPic(String smallPic) {
this.smallPic = smallPic;
}
public String getBm() {
return bm;
}
public void setBm(String bm) {
this.bm = bm;
}
public String getLayoutpage() {
return layoutpage;
}
public void setLayoutpage(String layoutpage) {
this.layoutpage = layoutpage;
}
@Override
public String toString() {
return "Newspaper [id=" + id + ", date=" + date + ", bigPic=" + bigPic
+ ", smallPic=" + smallPic + ", bm=" + bm
+ ", layoutpage=" + layoutpage + "]";
}
}
在 MainActivity.java中使用:
package com.cn.framework;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONObject;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.example.kuaidianframework.R;
import com.kuaidian.framework.entity.Paper;
import com.kuaidian.framework.jsonparseimpl.PaperParser;
import com.kuaidian.framework.util.LogUtil;
import com.kuaidian.framework.util.NetUtil;
public class MainActivity extends Activity {
private ImageView imageView;
private List<Paper> papers = new ArrayList<Paper>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView);
testJsonRequest();
testImageRequset();
}
//解析Json数据
private void testJsonRequest(){
String requestUrl = "http://42.51.16.158:8080/dsqy/action/phoneManager_getNewPaperByQi?type=1";
NetUtil.sendJsonObjectRequest(this, requestUrl, null, new Listener<JSONObject>(){
@Override
public void onResponse(JSONObject response) {
PaperParser newsPaperParser = PaperParser.getInstance();
//此处传入papers对象,就将数据存在该对象中
newsPaperParser.parseJson(papers, response);
for (int i = 0; i < papers.size(); i++) {
LogUtil.info(MainActivity.class, papers.get(i).getBigPic());
}
}
}, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//TODO
}
});
}
//显示网络图片
private void testImageRequset(){
//String imageUrl = "http://www.iqianyan.cc/simg/20140119/s_20140119195840.jpg";
String imageUrl = "http://b.hiphotos.baidu.com/pic/w%3D310/sign=9b24260fd53f8794d3ff4e2fe21a0ead/f636afc379310a55ba781b43b64543a98226102c.jpg";
NetUtil.loadImage(this, imageUrl, imageView, R.drawable.ic_launcher, 0);
}
}
不过在开发过程中也需要考虑到一些问题,比如:
1. 当图片过多过大时,在ListView中滚动图片错位的问题。
2. 图片过大,导致内存溢出等,需设置图片一级、二级缓存问题。