Java 类实例不会被销毁

标签 java android callback garbage-collection

我正在构建一个从硬编码 url 获取数据的 android 应用程序。

因为抓取时间比较长,所以先写了一个接口(interface)支持回调

public interface MyCallBack {
   void data_received(String data);
}

在主 Activity 中,我实现了MyCallBack

public class MainActivity extends AppCompatActivity implments MyCallBack {

  @Override
  public void data_received(String data) {
    Log.d("got data", data);
    // do something useful with data...
  }

  public void btn_getData_clicked(View view) {
       // a button is clicked, and fetching is started:
       BackgroundWorker bw = new BackgroundWorker(this);
       bw.execute("https://randomuser.me/api/");

      // after this point, bw does not leave the heap, 
     //  because BackgroundWorker keeps a reference to (this)
  }
}

我希望我的代码在按下按钮时进行单独的提取。 但我也希望消耗的/完成的/已经回调的实例消失,并离开堆,因为它们留下来没有意义。

因此,在 BackgroundWorker 类中,我在调用接口(interface)方法后立即将调用者设置为 null:

public class BackgroundWorker extends AsyncTask<String,Void,String> {

    MyCallBack caller;   // object to be called back when data arrives

    private static int instances_counter = 0;   // counts bw instances

    BackgroundWorker(MyCallBack cb) {
      caller = cb;
      instances_counter ++;
      Log.d("new bw object created", "current count: " + instances_counter );
    }

   @Override protected void finalize() throws Throwable {
      instances_counter --;
      Log.d("bw object destroyed","remaining count: " + instances_counter );
   }
    
   @Override String doInBackground(...) {...} // satisfy AsynTask 
   // and do the actual URL post/get stuff then forward the output
    // to onPostExecute() method

   
   @Override void onPostExecute(String s) {
      // I can check if caller is null first, but you get the idea.
      caller.data_received(s);

      caller = null;   // just so that this instance has no pointer to activity
   }
}

现在,当我多次单击该按钮时,我可以看到一个接一个创建的对象。我每次都在我的 Activity 中获取数据。

D/new bw object created: current count: 1

D/got data: {"results":[{"gender":"female" ...


D/new bw object created: current count: 2

D/got data: {"results":[{"gender":"male" ...


D/new bw object created: current count: 3

D/got data: {"results":[{"gender":"female" ...


D/new bw object created: current count: 4

D/got data: {"results":[{"gender":"female" ...


D/new bw object created: current count: 5

D/got data: {"results":[{"gender":"male" ...

但它们永远不会被摧毁。我担心我在某处造成内存泄漏,并且我的应用程序有时会由于我的内存管理不善而崩溃。

为什么这些实例没有被销毁?

最佳答案

finalize 中的日志输出方法不是确定对象是否导致内存泄漏的正确方法。

唯一可能引起怀疑的部分是您的 AsyncTask实例不仅对任何回调而且对整个 Activity 都有很强的引用。 .

仍然,Garbage Collector 训练有素无论如何都可以处理循环引用,但我承认我不知道它是否会等到 Activity被 gc'ed 收集 AsyncTask也是如此,否则它会尽快完成。

无论如何,您可以包装您的Callback WeakReference<T> 中的引用

private WeakReference<MyCallBack> caller;   // object to be called back when data arrives
// ...
caller = new WeakReference<>(cb);
// ...
if (caller.get() != null)
     // call callback

一旦需要内存,就会立即收集任务,这应该会给您带来很大的安全感。

But I also want the consumed/done/already called back instances to go away, and leave the heap since there is no point in them staying.

老实说,这不是你能决定的。

关于Java 类实例不会被销毁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49528580/

相关文章:

java - 来自服务器的意外文件结尾

java - OpenGL 正确附加纹理

java - BroadcastReceiver 的 onReceive 方法没有被调用

java - AdMob 横幅未在 Android (Cocos2d-x) 上显示测试广告

java - Android:如何允许共享并了解应用程序内部共享的内容

python - 在 Windows 上取消 python 中的停滞文件复制

javascript - Javascript 中的回调 ~ 如何在函数完成后触发事件?

java - 如何使用 Spring 4 MVC 配置 Jackson Streaming API

android - 如何在android中播放.gif文件

android - Android 中的自定义图库缩略图