簡體   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