Clean Inner Class 实现 Runnable

Clean Inner Class implementing Runnable

我有一个 Class 用于必须在内部 Classes 的 CustomView,两者都实现 Runnable 以在单独的线程中执行作业。

public class ValueSelector extends LinearLayout{

.....

private class AutoIncrementer implements Runnable {

    @Override
    public void run() {
        if (plusButtonIsPressed) {
            incrementValue();
            mHandler.postDelayed(new AutoIncrementer(), REPEAT_INTERVAL_MS);
        } else {
            mHandler.removeCallbacks(this);
            Thread.currentThread().interrupt();
        }
    }
}

private class AutoDecrementer implements Runnable {
    @Override
    public void run() {
        if (minusButtonIsPressed) {
            decrementValue();
            mHandler.postDelayed(new AutoDecrementer(), REPEAT_INTERVAL_MS);
        } else {
            mHandler.removeCallbacks(this);
            Thread.currentThread().interrupt();
        }
    }
}
}

如何正确清理它们? 当托管这些 CustomView 的 Activity 被销毁时,它们会自动被销毁吗?

干杯

不可以,如果 Activity 在定时器事件未决时被销毁会导致错误。为避免这种情况,对某些对象使用 Wea​​kReference,递减值。 但是,通常这是不好的做法 - 混合 UI 和一些 ligic,因为它很难测试。考虑使用 rxJava 库,这看起来像

 Subscriptioin s = Observable.just(100, TimeUnit.Milliseconds)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.computation())
.subscribe(t -> decrementValue());

在您的 onPause() 方法中通过

取消该操作
if (s != null && !s.inUnsubscribed()) { 
s.unsubscribe(); 
s = null; 
}

它不会被破坏导致内存泄漏,因为您的线程将对您的视图具有强引用,因此您的 activity。

使内部 class 静态化并保持对 运行 方法中所需变量的弱引用。

您可以做的第二件事是中断您的线程,当您查看与 window 分离并检查 运行 方法是否线程被中断时,尽管如果您的线程没有必要线程没有做太多工作。

这是您的 运行nable 的样子

private static class AutoDecrementer implements Runnable {

    AutoDecrementer (ValueSelector valueSelector ){
       this.weakRef = new WeakReference<>(valueSelector);
    }      


    @Override
    public void run() {
         ValueSelector valueSelector =  (ValueSelector )weakRef.get();
         if(valueSelector == null){
            return ;
          }  

        if (valueSelector.minusButtonIsPressed) {
            valueSelector .decrementValue();
            valueSelector .mHandler.postDelayed(new AutoDecrementer(), REPEAT_INTERVAL_MS);
        } else {
            valueSelector.mHandler.removeCallbacks(this);
            Thread.currentThread().interrupt();
        }
    }
}

我没有检查任何错误。