Volley网络框架发送请求后,页面退出时需要取消已经添加但没有完成的请求,否则可能导致内存泄露甚至Crash。
Volley的使用方式
请求队列RequestQueue为单例,避免重复创建。
-
public class MyVolley {
-
private static RequestQueue mRequestQueue;
-
public static RequestQueue getRequestQueue() {
-
if (mRequestQueue != null) {
-
return mRequestQueue;
-
} else {
-
throw new IllegalStateException("RequestQueue not initialized");
-
}
-
}
-
public static void addRequest(BaseRequest<ResponseData> request, String tag) {
-
request.setTag(tag);
-
getRequestQueue().add(request);
-
getRequestQueue().start();
-
}
-
}
每个Activity有一个TAG,请求时使用这个TAG,onDestroy时通过TAG取消。
-
public class SampleActivity extends Activity {
-
private static final String TAG = "SampleActivity";
-
//...
-
MyVolley.addRequest(request, TAG);
-
public void onDestroy() {
-
MyVolley.cancelAll(TAG);
-
super.onDestroy();
-
}
-
}
出现的问题
重复进入一个Activity时,有时会出现第二次进入时,网络请求始终不能加载出来。
原因:当一个页面退出时,onStop会立即调用,但安卓并不保证onDestroy也会立即调用。onDestroy的调用可能有延迟,当第二个SampleActivity请求刚发起还没返回结果,刚好前一个SampleActivity的onDestroy调用了,因为两者的TAG相同,于是第二个SampleActivity的网络请求被取消掉了,永远不会加载出结果。
解决方法
-
不使用单例请求队列。这种做法效率低下,不考虑。
-
onStop中调用cancel。官方资料是这么用的,但是不一定能满足需求:http://developer.android.com/intl/zh-cn/training/volley/simple.html
-
每次创建Activity,生成一个新的TAG。例如可以直接在基类中用Activity的ClassName和hashCode或时间戳生成。这种做法相对比较好。
-
直接将Activity实例自身作为TAG传入,每次创建新的Activity实例,TAG就变了。这种做法有点担心内存泄露,不是很推荐。
综上,选用方法3解决问题。