作为开发安卓者,选择网络请求框架非常重要,之前公司上的产品使用的httpClient+httpUrlConnection封装Asynctask做为网络请求的框架,出现了很卡的状况,当然也有别的方面的原因.这里建议使用在google开发手册上的volley框架作为网络请求的框架,google推出的东西建议大家都可以去学习一下,比如说apidemo里面的源码,还是很具有参考性和学习性.本人也是周末闲来无事参阅google手册和大家一起学习一下volley这个网络框架,当然如果需要另一个优秀的网络请求框架okhttp视频可以向我拿,详细的讲述了okhttp网络请求框架的原理和使用.
1.走进volley
在高版本的Api中,你可以通过创建一个RequestQueue和请求实体来使用volley,RequestQueue(请求队列)管理的工作线程(理解为线程池的概念)可以执行网络请求,并且能够读写入缓存中,最重要的是可以解析响应的操作.通过请求实体解析响应的内容.同时volley还负责将分配解析好的响应实体回调给主线程,在这个回调中就可以做一些跟新UI的操作(回调是在主线程,也就是说请求队列上管理的工作线程处理完请求网络操作后可以把请求结果返回主线程),同时还提供了取消网络请求的一些处理.
原理:volley内部维护这三个线程池,分别是cache thread,network线程,main线程
cache线程:如果你的请求在缓存的线程池中,那么会把解析好的响应结果传递给主线程
network线程池:维护这多个work线程,在最先可用的work线程,通过http协议请求网络,解析响应结果和写入缓存中,同时把解析的结果传递给主线程
关系:当volley这个对象将请求的添加到请求队列时,如果请求存在缓存中,并且被筛选出来加入到缓存线程中,缓存线程会将缓存的解析结果发送给主线程.如果请求不在缓存中,那么请求就会加入network队列中,当有network线程池中有可用线程时,就会出列,请求会在在work 线程中通过http协议请求网络,并且解析结果把解析好的结果传递给主线程,在主线程的回调函数中可以对结果直接进行UI的跟新
此外请求队列还提供了cancel这个方法,确保在取消后,保证响应的handler不被调用,这样你就不用getActivity为空,这个垃圾也是不存在的,利用这个特点你可以在ontop()中调用这个方法,取消这个请求任务,你可以给特定的请求设置一个tag,调用queueRequest,cancle(Tag),这个任务就对应的取消且不会发生调用
-
public static final String TAG = "MyTag"; StringRequest stringRequest; // Assume this exists. RequestQueue mRequestQueue; // Assume this exists. // Set the tag on the request. stringRequest.setTag(TAG); // Add the request to the RequestQueue. mRequestQueue.add(stringRequest);
-
@Override protected void onStop () { super.onStop(); if (mRequestQueue != null) { mRequestQueue.cancelAll(TAG); } }
简单使用(参阅google开发手册):
... // Instantiate the RequestQueue. RequestQueue queue = Volley.newRequestQueue(this); String url ="http://www.google.com"; // Request a string response from the provided URL. StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { // Display the first 500 characters of the response string. mTextView.setText("Response is: "+ response.substring(0,500)); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { mTextView.setText("That didn't work!"); } }); // Add the request to the RequestQueue. queue.add(stringRequest);
2.初始化RequestQueue
在很多app使用第三方框架时,都会使用单例模式来创建对象,这样确保在整个应用中,该对象只有一个,确保了对象重复的创建,使得一个对象贯穿整个应用的生命周期
上面提到了RequestQueue,维护了network线程池和cache线程,所以在创建RequestQueue时,我们也需要指定一些关于这两个对象的配置
public class MySingleton { private static MySingleton mInstance; private RequestQueue mRequestQueue; private ImageLoader mImageLoader; private static Context mCtx; private MySingleton(Context context) { mCtx = context; mRequestQueue = getRequestQueue(); mImageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() { private final LruCache<String, Bitmap> cache = new LruCache<String, Bitmap>(20); @Override public Bitmap getBitmap(String url) { return cache.get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { cache.put(url, bitmap); } }); } public static synchronized MySingleton getInstance(Context context) { if (mInstance == null) { mInstance = new MySingleton(context); } return mInstance; } public RequestQueue getRequestQueue() { if (mRequestQueue == null) { // getApplicationContext() is key, it keeps you from leaking the // Activity or BroadcastReceiver if someone passes one in. mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext()); } return mRequestQueue; } public <T> void addToRequestQueue(Request<T> req) { getRequestQueue().add(req); } public ImageLoader getImageLoader() { return mImageLoader; } }
Volley.newRequestQueue(mCtx.getApplicationContext());//通过该初始化方法,保证对象的生命周期为app的生命周期