直接把注释粘过来:
* Volley使用讲解: * 要实现网络数据请求主要要记住下面三步骤: * 1.创建RequestQueue对象 * 2.创建XXRequest对象(XX代表String,JSON,Image等等) * 3.把XXRequest对象添加到RequestQueue中即可 * 该通过Volley的静态方法newRequestQueue(Context)来获取一个请求队列对象 * 内部设计有请求缓存,系统版本区分请求 * 并且设计适合于高并发 *
第一步 新建一个application ,并创建
RequestQueue
/**Acein20160202*/public class MyApplication extends Application { private static RequestQueue mQueue; @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); mQueue = Volley.newRequestQueue(getApplicationContext()); } public static RequestQueue getRequstQueue() { return mQueue; }}
然后在 /VollyDemo/AndroidManifest.xml <application> 标签中添加 : 添加红色部分 再添加一个网络请求权限
创建StringRequest对象来发起HTTP请求,然后接收相应数据:
* * 创建StringRequest对象传入四个参数: * 请求方法GET/POST/或者其他 * 请求服务器的目标地址 * 服务器数据成功响应回调 * 服务器数据失败响应回调public class MainActivity extends Activity { private MyApplication mApplication; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); vollyGet(); mApplication = new MyApplication(); } public void vollyGet() { String url = "http://apis.juhe.cn/mobile/get?phone=15836300559&key=XXXXXXXXXXX你申请的keyXXXXXXXXXXXX"; StringRequest stringRequest = new StringRequest(Method.GET, url, new Listener() { //请求成功调用 @Override public void onResponse(String arg0) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, arg0, Toast.LENGTH_LONG).show(); } }, new ErrorListener() { //请求失败调用 @Override public void onErrorResponse(VolleyError arg0) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show(); } }); stringRequest.setTag("getString"); mApplication.getRequstQueue().add(stringRequest); }}
这是最简单的String get 因为是给新手看的 所以 这样写很不优雅 但是给新手看很好,
下面来看JSONget
public void vollyGet() { String url = "http://apis.juhe.cn/mobile/get?phone=15836300559&key=XXXXXXX你申请的keyXXXXXXXXXXXXX"; JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Method.GET, url, null, new Listener() { @Override public void onResponse(JSONObject arg0) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show(); } }, new ErrorListener() { @Override public void onErrorResponse(VolleyError arg0) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show(); } }); jsonObjectRequest.setTag("jsonget"); mApplication.getRequstQueue().add(jsonObjectRequest); }
来看下StringRequst POST:跟GET唯一不同是 重写了 getParams方法 ,这样post的时候就会自动调用
StringRequest stringRequest = new StringRequest(Method.POST, url, new Listener() { @Override public void onResponse(String arg0) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show(); } }, new ErrorListener() { @Override public void onErrorResponse(VolleyError arg0) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show(); } }){ @Override protected Map getParams() throws AuthFailureError { Map map = new HashMap (); map.put("phone", "15836300559"); map.put("key", "f64ff5c4c517da17761f112d6c3c0da0"); return map; } }; stringRequest.setTag("ace"); mApplication.getRequstQueue().add(stringRequest); }
来看JSonRequest的POST 非常有趣 JSonRequest 的Method.POST有很多的坑, 还有 网上那些写错的我就纳闷了 你是怎么得到返回数据的 ,或者说你真的实验了吗
来! 看第一个坑: 跟StringRequst 一样 我重写了getparams方法.
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Method.POST, url,null, new Listener() { @Override public void onResponse(String arg0) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show(); } }, new ErrorListener() { @Override public void onErrorResponse(VolleyError arg0) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show(); } }){ @Override protected Map getParams() throws AuthFailureError { Map map = new HashMap (); map.put("phone", "15836300559"); map.put("key", "f64ff5c4c517da17761f112d6c3c0da0"); return map; } }; stringRequest.setTag("ace"); mApplication.getRequstQueue().add(stringRequest); }
JsonObjectRequest构造中的参数传null,和StringRequest一样去重写getParams()方法来传参。貌似是没问题的?
使用这段代码拿不到服务器返回的数据,反馈的结果是没有传参给服务器。那就看看参数最终是在哪里提交给服务器的。
Debug HurlStack.java中的addBodyIfExists()这个方法,发现request.getBody()==null,也就是没有接收到参数。
StringRequest可以重写getParams来传参是因为Request中的这个方法:
public byte[] getBody() throws AuthFailureError { Mapparams = getParams(); if (params != null && params.size() > 0) { return encodeParameters(params, getParamsEncoding()); } return null; }
重写的getParams的结果会传到这里。
JsonObjectRequest不能重写getParams来传参是因为JsonRequest中的这个方法:
JsonRequest.java
@Override public byte[] getBody() { try { return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET); } catch (UnsupportedEncodingException uee) { VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mRequestBody, PROTOCOL_CHARSET); return null; } }
重写了Request.getBody(),这段代码说明 mRequestBody这个变量就是它的参数。这个变量就存在与JsonRequest的构造函数中。
说明,JsonObjectRequest的传参必须通过构造来传,重写getParams()是无法传递的。
下面按正常思路,来踩第二个坑。给JsonObjectRequest的构造传递参数。又会出现什么问题?
private void vollyPost() { String url = "http://apis.juhe.cn/mobile/get?"; Mapmap = new HashMap (); map.put("phone", "15836300559"); map.put("key", "f64ff5c4c517da17761f112d6c3c0da0"); JSONObject jObject = new JSONObject(map); JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Method.POST, url, jObject ,new Listener () { @Override public void onResponse(JSONObject arg0) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show(); } }, new ErrorListener() { @Override public void onErrorResponse(VolleyError arg0) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show(); } }); jsonObjectRequest.setTag("json_post"); mApplication.getRequstQueue().add(jsonObjectRequest);}
JsonOnjectRequest Post 可能会出错的方式 : * 这里的思路是调用JsonObjectRequest带参构造,传参进入不就得了? * 但是这里还是请求不到数据。 * 原因是使用JsonObjectRequest 如果服务器接受的参数类型是 http://....?key1=value1&key2=value2, * 而不是json串{key1 : value1,key2 : value2...},参数就会传不进去。 * 可以在 HurlStack.java 的addBodyIfExists方法中看到你传入的参数信息。
一个大写的坑爹,那些教程拜托请不要误导人好吗?特别像我这种菜鸟,很耗费时间的!
怎么办呢?
我找到这个方法 现在在写
http://blog.csdn.net/onlysnail/article/details/47905375
http://www.open-open.com/lib/view/open1434090628333.html
上面的方法还在解决中,我的借口不支持JSON格式的提交所以要重新自定义JsonRequst
接下来是ImageRequest:
- 第三第四个参数分别用于指定允许图片最大的宽度和高度,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,
- 指定成0的话就表示不管图片有多大,都不会进行压缩。
- @param url
- 图片地址
- @param listener
- @param maxWidth
- 指定允许图片最大的宽度
- @param maxHeight
- 指定允许图片最大的高度
- @param decodeConfig
- 指定图片的颜色属性,Bitmap.Config下的几个常量.
- @param errorListener
public class MainActivity extends Activity { private MyApplication mApplication; private ImageView iv_image; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String url ="http://pic.cnblogs.com/avatar/859887/20160120170921.png"; mApplication = new MyApplication(); initView(); ImageRequest mRequest = new ImageRequest(url, new Listener() { @Override public void onResponse(Bitmap arg0) { // TODO Auto-generated method stub iv_image.setImageBitmap(arg0); } }, 0, 0, Config.RGB_565, new ErrorListener() { @Override public void onErrorResponse(VolleyError arg0) { // TODO Auto-generated method stub iv_image.setImageResource(mipmap.sym_def_app_icon); } }); mApplication.getRequstQueue().add(mRequest); } private void initView() { // TODO Auto-generated method stub iv_image = (ImageView) findViewById(R.id.iv_imag); } }
ImageLoad + LruCache
Lrucache 是图片的内存缓存
public class BitmapCache implements ImageCache{ public LruCachecache; public BitmapCache() { // TODO Auto-generated constructor stub // 拿到最大内存 final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // 拿到内存的八分之一来做图片内存缓存 final int cacheSize = maxMemory / 8; cache =new LruCache (cacheSize){ @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes() * value.getHeight() / 1024; } }; } @Override public Bitmap getBitmap(String arg0) { // TODO Auto-generated method stub return cache.get(arg0); } @Override public void putBitmap(String arg0, Bitmap arg1) { cache.put(arg0, arg1); }}
MainActivity
public class MainActivity extends Activity { private MyApplication mApplication; private ImageView iv_image; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String url ="http://pic.cnblogs.com/avatar/859887/20160120170921.png"; mApplication = new MyApplication(); initView(); BitmapCache bCache = new BitmapCache(); ImageLoader loader = new ImageLoader(mApplication.getRequstQueue(), bCache); // getImageListener(imageView控件对象,默认图片地址,失败图片地址); ImageListener listener = ImageLoader.getImageListener(iv_image, R.drawable.ic_launcher, R.drawable.ic_launcher); // get(图片地址,listener,宽,高);自动帮你处理图片的宽高再也不怕大图片的oom了 loader.get(url, listener,160,160); } private void initView() { // TODO Auto-generated method stub iv_image = (ImageView) findViewById(R.id.iv_imag); } }
Volley还提供的加载图片的控件com.android.volley.NetworkImageView。(这个控件在被从父控件detach的时候,会自动取消网络请求的,即完全不用我们担心相关网络请求的生命周期问题,而且NetworkImageView还会根据你对图片设置的width和heigh自动压缩该图片不会产生多的内存,还有NetworkImageView在列表中使用不会图片错误)
使用方法:
private void networkImageViewUse(NetworkImageView iv, String url) { ImageLoader imLoader = new ImageLoader(mQueue, new BitmapLruCache()); iv.setDefaultImageResId(R.drawable.ic_launcher); iv.setErrorImageResId(R.drawable.ic_launcher); iv.setImageUrl(url, imLoader); }
我们说了这么多都是请求,那么如何取消请求呢?
1.activity自动销毁时它会自定取消所有请求。
2.给请求设置标签:
request.setTag("My Tag");
取消所有指定标记的请求:
request.cancelAll("My Tag");
有兴趣的可以读下 Volly的架构 主线程啊 网络请求线程 缓存线程
http://blog.csdn.net/superjimmy/article/details/45601661
http://www.15yan.com/story/lHkq4Oi9Y2a/
好了 今天的教程就到这里~