我正在使用在侦听器事件中取消并重新启动的计时器。除了计时器线程泄漏整个外部类之外,一切正常。
我的计时器实现如下:
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()
答案 0 :(得分:3)
如果您认为问题在于匿名内部类包含对外部类的引用,那么只需使用静态命名的内部类 - 这将不包含引用。把这样的东西放在你的班级里面:
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);
}
}
答案 1 :(得分:1)
我也有同样的问题。我发现,当我将Timer
定义为全局变量,并且在活动结束时未将其设置为null
时,总是会导致内存泄漏。
当我将Timer
定义为local 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;
}
}