在使用leakcanary之后,我发现我的应用程序中有很多漏洞,大多数都是由于volley的匿名回调侦听器造成的。所以我写了一个util(下面)类,它使用静态回调和 WeakReference
参考 Context
还有匿名回电。但是,当我第一次打开应用程序时,即冷启动,在请求发出后不久,上下文就会被gced,但在热启动期间,一切正常。同样,这只发生在应用程序中的第一个活动中。
任何处理内存泄漏的替代方法都是受欢迎的。
public abstract class VUtil {
public static final String TAG = VUtil.class.getSimpleName();
public interface JsonCallback {
void onSuccess(JSONObject response);
}
public interface StringCallback {
void onSuccess(String response);
}
public interface ErrorCallback {
void onError(VolleyError error);
}
public static class JsonResponseListener implements Response.Listener<JSONObject> {
private final WeakReference<Context> mContextWeakReference;
private final WeakReference<JsonCallback> mCallbackWeakReference;
public JsonResponseListener(Context context, JsonCallback callback) {
mContextWeakReference = new WeakReference<>(context);
mCallbackWeakReference = new WeakReference<>(callback);
}
@Override
public void onResponse(JSONObject jsonObject) {
Context context = mContextWeakReference.get();
JsonCallback callback = mCallbackWeakReference.get();
if (context != null && callback != null) {
callback.onSuccess(jsonObject);
} else {
Log.d(TAG, "Context was GCed");
}
}
}
public static class StringResponseListener implements Response.Listener<String> {
private final WeakReference<Context> mContextWeakReference;
private final WeakReference<StringCallback> mCallbackWeakReference;
public StringResponseListener(Context context, StringCallback callback) {
mContextWeakReference = new WeakReference<>(context);
mCallbackWeakReference = new WeakReference<>(callback);
}
@Override
public void onResponse(String response) {
Context context = mContextWeakReference.get();
StringCallback callback = mCallbackWeakReference.get();
if (context != null && callback != null) {
callback.onSuccess(response);
} else {
Log.d(TAG, "Context was GCed");
}
}
}
public static class ErrorListener implements Response.ErrorListener {
private final WeakReference<Context> mContextWeakReference;
private final WeakReference<ErrorCallback> mCallbackWeakReference;
public ErrorListener(Context context, ErrorCallback callback) {
mContextWeakReference = new WeakReference<>(context);
mCallbackWeakReference = new WeakReference<>(callback);
}
@Override
public void onErrorResponse(VolleyError error) {
Context context = mContextWeakReference.get();
ErrorCallback callback = mCallbackWeakReference.get();
if (context != null && callback != null) {
callback.onError(error);
} else {
Log.d(TAG, "Context was GCed");
}
}
}
}
2条答案
按热度按时间b4wnujal1#
gc依赖于正在发生的许多事情。造成这种情况的一个可能原因是,当你在“冷启动”后执行第一个请求时,你的应用程序必须初始化各种自定义对象、片段、活动、视图缓存等,因此在增加堆之前需要内存,从而执行gc。
不过,我建议的解决方案是更改您的体系结构。
1) 似乎你一直引用上下文,但它从来没有被使用过。放下它
2) 你有凌空的回调,委托给你的自定义回调,你需要通过无论如何,为什么不你简单地使用一套回调,你传递给各自的请求。
3) 你有自己的习惯性回电,但你不能没有它们。周引用并不是解决内存泄漏的最终方法。你必须弄清楚为什么裁判在你不需要的时候还在那里。
因此,如果泄漏问题出现在jsoncallback中,那么stringcallback和errorcallback实现只需尝试解决这个问题,而不是让链变长并在最后切断它。
xsuvu9jc2#
多亏乔乔的回答帮助我找到了解决办法
始终使用
addToRequestQueue(request, TAG)
. 在这里TAG
bit是当请求的活动/片段/视图或任何内容被gced时,我们用来取消它们的请求我所做的是创建一个基本活动,并在该活动中添加所有请求取消代码。下面是它的样子
getRequestQueue().cancelAll(tag);