Volley网络请求取消的实现

Volley网络框架发送请求后,页面退出时需要取消已经添加但没有完成的请求,否则可能导致内存泄露甚至Crash。

Volley的使用方式

请求队列RequestQueue为单例,避免重复创建。

  1. public class MyVolley {

  2. private static RequestQueue mRequestQueue;

  3. public static RequestQueue getRequestQueue() {

  4. if (mRequestQueue != null) {

  5. return mRequestQueue;

  6. } else {

  7. throw new IllegalStateException("RequestQueue not initialized");

  8. }

  9. }

  10. public static void addRequest(BaseRequest<ResponseData> request, String tag) {

  11. request.setTag(tag);

  12. getRequestQueue().add(request);

  13. getRequestQueue().start();

  14. }

  15. }

每个Activity有一个TAG,请求时使用这个TAG,onDestroy时通过TAG取消。

  1. public class SampleActivity extends Activity {

  2. private static final String TAG = "SampleActivity";

  3. //...

  4. MyVolley.addRequest(request, TAG);

  5. public void onDestroy() {

  6. MyVolley.cancelAll(TAG);

  7. super.onDestroy();

  8. }

  9. }

出现的问题

重复进入一个Activity时,有时会出现第二次进入时,网络请求始终不能加载出来。

原因:当一个页面退出时,onStop会立即调用,但安卓并不保证onDestroy也会立即调用。onDestroy的调用可能有延迟,当第二个SampleActivity请求刚发起还没返回结果,刚好前一个SampleActivity的onDestroy调用了,因为两者的TAG相同,于是第二个SampleActivity的网络请求被取消掉了,永远不会加载出结果。

解决方法

  1. 不使用单例请求队列。这种做法效率低下,不考虑。

  2. onStop中调用cancel。官方资料是这么用的,但是不一定能满足需求:http://developer.android.com/intl/zh-cn/training/volley/simple.html

  3. 每次创建Activity,生成一个新的TAG。例如可以直接在基类中用Activity的ClassName和hashCode或时间戳生成。这种做法相对比较好。

  4. 直接将Activity实例自身作为TAG传入,每次创建新的Activity实例,TAG就变了。这种做法有点担心内存泄露,不是很推荐。

    参考: http://www.pocketdigi.com/20140511/1315.html

综上,选用方法3解决问题。