Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 截击静态回调侦听器上下文GCed_Java_Android_Memory Leaks_Android Volley - Fatal编程技术网

Java 截击静态回调侦听器上下文GCed

Java 截击静态回调侦听器上下文GCed,java,android,memory-leaks,android-volley,Java,Android,Memory Leaks,Android Volley,在使用之后,我发现我的应用程序中有很多漏洞,大多数都是由于截击的匿名回调侦听器造成的。因此我编写了一个Util(如下)类,它使用静态回调和WeakReference来保持对Context的引用和匿名回调。但是,当我第一次打开应用程序时,即冷启动时,在发出请求后不久就会对上下文进行GCD,但在热启动期间,一切正常。而且,这只会发生在应用程序中的第一个活动中 我们也欢迎使用截击处理内存泄漏的任何其他方法,这些方法可以正常工作 public abstract class VUtil { pu

在使用之后,我发现我的应用程序中有很多漏洞,大多数都是由于截击的匿名回调侦听器造成的。因此我编写了一个Util(如下)类,它使用静态回调和
WeakReference
来保持对
Context
的引用和匿名回调。但是,当我第一次打开应用程序时,即冷启动时,在发出请求后不久就会对上下文进行GCD,但在热启动期间,一切正常。而且,这只会发生在应用程序中的第一个活动中

我们也欢迎使用截击处理内存泄漏的任何其他方法,这些方法可以正常工作

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");
            }
        }
    }
}
公共抽象类VUtil{
公共静态最终字符串标记=VUtil.class.getSimpleName();
公共接口JsonCallback{
成功时无效(JSONObject响应);
}
公共接口字符串回调{
void onSuccess(字符串响应);
}
公共接口错误回调{
无效错误(截击错误);
}
公共静态类JsonResponseListener实现Response.Listener{
私有最终WeakReference mContextWeakReference;
私人最终WeakReference mCallbackWeakReference;
公共JsonResponseListener(上下文上下文,JsonCallback回调){
mContextWeakReference=新的WeakReference(上下文);
mCallbackWeakReference=新的WeakReference(回调);
}
@凌驾
公共void onResponse(JSONObject JSONObject){
Context Context=mContextWeakReference.get();
JsonCallback callback=mCallbackWeakReference.get();
if(上下文!=null&&callback!=null){
onSuccess(jsonObject);
}否则{
Log.d(标签“上下文为GCed”);
}
}
}
公共静态类StringResponseListener实现Response.Listener{
私有最终WeakReference mContextWeakReference;
私人最终WeakReference mCallbackWeakReference;
公共StringResponseListener(上下文上下文,StringCallback){
mContextWeakReference=新的WeakReference(上下文);
mCallbackWeakReference=新的WeakReference(回调);
}
@凌驾
公共void onResponse(字符串响应){
Context Context=mContextWeakReference.get();
StringCallback callback=mCallbackWeakReference.get();
if(上下文!=null&&callback!=null){
callback.onSuccess(响应);
}否则{
Log.d(标签“上下文为GCed”);
}
}
}
公共静态类ErrorListener实现Response.ErrorListener{
私有最终WeakReference mContextWeakReference;
私人最终WeakReference mCallbackWeakReference;
公共ErrorListener(上下文上下文,ErrorCallback){
mContextWeakReference=新的WeakReference(上下文);
mCallbackWeakReference=新的WeakReference(回调);
}
@凌驾
公共无效onErrorResponse(截击错误){
Context Context=mContextWeakReference.get();
ErrorCallback callback=mCallbackWeakReference.get();
if(上下文!=null&&callback!=null){
callback.onError(错误);
}否则{
Log.d(标签“上下文为GCed”);
}
}
}
}

GC取决于正在发生的许多事情。这种情况的一个可能原因是,当您在“冷启动”后执行第一个请求时,应用程序必须初始化各种自定义对象、片段、活动、视图缓存等,因此在增加堆之前需要内存,从而执行GC

然而,我提出的解决方案是改变您的体系结构

1) 似乎你一直在引用上下文,但它从未被使用过。放下它

2) 您有大量回调,这些回调委托给您需要传递的自定义回调,为什么不使用一组回调传递给相应的请求呢

3) 你有一周的自定义回调,但你不能没有它们。周引用不是内存泄漏的最终解决方案。你必须找出为什么裁判在你不需要的时候还在那里

所以,如果您在JsonCallback中泄漏了问题,StringCallback和ErrorCallback实现只需尝试解决这个问题,而不是使链变长并在最后将其切断。

多亏了djodjo的回答,帮助我找到了解决方案

  • 始终使用
    addToRequestQueue(请求、标记)
    。这里
    TAG
    bit是当请求的活动/片段/视图或任何内容被GCed时,我们用来取消请求的内容

  • 我所做的是创建一个基本活动,并在该活动中添加所有请求取消代码。这是它的样子

    public abstract class BaseActivity extends AppCompatActivity {
    
        public final String tag;
    
        public BaseActivity() {
            super();
            tag = getClass().getSimpleName();
        }
    
        @Override
        protected void onDestroy() {
            App.getInstance().cancelRequests(tag);
            super.onDestroy();
        }
    
        protected <T> void addToRequestQueue(Request<T> request) {
            App.getInstance().addToRequestQueue(request, tag);
        }
    
    }
    
    从此
    BaseActivity
    扩展您的活动,并使用
    addToRequestQueue
    发出请求,当您的活动被销毁时,请求将自动取消。对fragment/dialog/anythis执行类似的操作


    如果您从任何其他地方发出的请求没有遵循生命周期,请确保它没有绑定到任何
    上下文
    ,您会没事的。

    @Sourabh您如何在Stringrequest中传递该类对象,以及如何从该响应将该响应重定向到相应的activity responsepass对象作为
    MyClass。这
    ?我不明白你所说的
    将响应重定向到不同活动的相应活动响应是什么意思,我正在进行网络呼叫,因此无论收到什么响应,我都必须将其重定向到特定活动。@Midslefko,我还想在截击请求中添加cancelAll。我应该在哪里添加“getRequestQueue().cancelAll(tag);”,它是单例模式吗?活动生命周期?我很困惑。非常感谢。将它添加到您的
    应用程序
    实例中,因为它的Appli
    
    getRequestQueue().cancelAll(tag);