繁体   English   中英

计时器内存泄漏

[英]Memory leak with Timer

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

我的计时器实现如下:

        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毫秒+之后),定时器以及对上下文的引用不会被垃圾收集。

在这种情况下,即使在线程完成之后,上下文仍然不会被释放吗?

最后我该如何解决这个漏洞? 我将计时器设置为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
 }

在listview的滚动事件上调用moveHeader()

如果你认为问题是匿名内部类持有对外部类的引用,那么只需使用静态命名的内部类 - 这将不包含引用。 在你的课堂上放置这样的东西:

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);
    }
}

我和你有同样的问题。 我发现当我将Timer定义为全局var并且在活动结束时不将其设置为null时,它总是导致内存泄漏。 当我将Timer定义为局部var或将其设置为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;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM