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解决问题。