【问题标题】:Memory leak with TimerTimer 内存泄漏
【发布时间】:2023-03-05 15:03:01
【问题描述】:

我正在使用在侦听器事件上取消并重新启动的计时器。除了定时器线程泄漏了整个外部类之外,一切都很好。

我的定时器实现如下:

        if(timer != null) {
            timer.cancel();
            timer = null;
            timer = new Timer();
        }
        timer.schedule(new TimerTask() { // Thread leaks!!!!
            @Override
            public void run() {
              mCallback.onHeaderMoving(newToolbarTranslationY );
            }
        } , 150);

我使用 MAT Analyzer 来追踪问题并最终解决了问题。我还用回调注释掉了这条线,但线程仍然泄漏,所以它肯定是计时器本身。但是我真的不明白该代码有什么问题。

据我研究,问题在于匿名内部类 (new Timertask()) 持有对外部类的引用,因此可能泄漏整个上下文。但是我仍然不明白为什么在线程用完后(150 ms + 之后)计时器以及对上下文的引用没有被垃圾收集。

这种情况下的上下文是否在线程完成后仍然没有释放?

最后我该如何解决这个泄漏?我将计时器设置为 null,但这并没有解决我的问题。

编辑

 private OnHeaderMovingCallBack mCallback;
 private Timer timer = new Timer();

 //... some other parameters


public ScrollingToolbarManager(View toolbar , View pagerStrip , AbsListView listView , OnHeaderMovingCallBack headerMovingCallBack){
    this.toolbar = toolbar;
    this.pagerStrip = pagerStrip;

    this.listView = listView;

    mCallback = headerMovingCallBack;

    changeStartValues();

}

public static interface OnHeaderMovingCallBack{
    public void onHeaderMoving(int translationY);
}

 public void moveHeader(){

      //... some calculations

    //timer implementation from above
 }

在列表视图的滚动事件上调用 moveHeader()

【问题讨论】:

  • timer 是如何以及在哪里定义的?
  • 定时器定时器;就在类的标题中。你是这个意思吗?
  • 是的,但是在您的问题中发布确切的代码,包括所有修饰符。没有类的标题这样的东西。
  • 我只是指在课程开头的标题:)
  • 我理解你,但我还是想看看真正的代码 :) 你有没有尝试在一个不是 Activity 的类中这样做?

标签: java android multithreading memory-leaks timer


【解决方案1】:

如果您认为问题在于匿名内部类持有对外部类的引用,那么只需使用静态命名的内部类 - 这将不持有任何引用。在你的班级里放这样的东西:

static class MyTimerTask extends TimerTask {
    private OnHeaderMovingCallBack mCallback;
    int newToolbarTranslationY;

    public MyTimerTask(OnHeaderMovingCallBack mCallback, int newToolbarTranslationY) {
        this.mCallback = mCallback;
        this.newToolbarTranslationY = newToolbarTranslationY;
    }

    @Override
    public void run() {
        mCallback.onHeaderMoving(newToolbarTranslationY);
    }
}

【讨论】:

    【解决方案2】:

    我和你有同样的问题。我发现当我将Timer定义为全局变量并且在活动完成时不将其设置为null时,它总是会导致内存泄漏。 当我将Timer 定义为本地变量或将其设置为null 时,问题就消失了。但我不明白为什么。如果你解决了,请告诉我你的解决方法,谢谢!

    public class TestActivity extends AppCompatActivity {
        private Timer mTimer;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_test);
            mTimer = new Timer();
            mTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, 0);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mTimer = null;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-08
      • 2013-01-20
      • 2011-10-31
      • 2019-08-10
      • 2013-06-24
      相关资源
      最近更新 更多