对Volley开源框架 进行封装
ygp8
9年前
Volley是Ficus Kirpatrick在Gooogle I/O 2013发布的一个处理和缓存网络请求的库,能使网络通信更快,更简单,更健壮。
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. 图片过大,导致内存溢出等,需设置图片一级、二级缓存问题。
来自:http://blog.csdn.net/gao_chun/article/details/34117083