Java 干净的内部类实现Runnable

Java 干净的内部类实现Runnable,java,android,multithreading,performance,runnable,Java,Android,Multithreading,Performance,Runnable,我为CustomView提供了一个类,该类必须包含内部类,这两个类都实现Runnable以在单独的线程中执行作业 public class ValueSelector extends LinearLayout{ ..... private class AutoIncrementer implements Runnable { @Override public void run() { if (plusButtonIsPressed) {

我为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的活动被销毁时,它们是否会自动销毁


干杯

否,如果活动在计时器事件仍挂起时被销毁,则会导致错误。要避免这种情况,请使用对某个对象的WeakReference,递减值。 但是,通常情况下,将UI和一些语言混合使用是不好的做法,因为它很难测试。考虑使用RXJava库,这将看起来像

 Subscriptioin s = Observable.just(100, TimeUnit.Milliseconds)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.computation())
.subscribe(t -> decrementValue());
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();
        }
    }
}
在onPause()方法中,通过

if (s != null && !s.inUnsubscribed()) { 
s.unsubscribe(); 
s = null; 
}

否,如果在计时器事件仍挂起时销毁活动,则会导致错误。要避免这种情况,请使用对某个对象的WeakReference,递减值。 但是,通常情况下,将UI和一些语言混合使用是不好的做法,因为它很难测试。考虑使用RXJava库,这将看起来像

 Subscriptioin s = Observable.just(100, TimeUnit.Milliseconds)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.computation())
.subscribe(t -> decrementValue());
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();
        }
    }
}
在onPause()方法中,通过

if (s != null && !s.inUnsubscribed()) { 
s.unsubscribe(); 
s = null; 
}

它不会被破坏而导致内存泄漏,因为您的线程将对您的视图以及您的活动有一个强引用

使内部类保持静态,并保持对run方法中所需变量的弱引用

您可以做的第二件事是中断您的线程,当您从窗口中分离视图时,如果线程被中断或未被中断,请检查run方法,但如果您的线程没有做太多工作,则不需要这样做

以下是您的runnable的外观

 Subscriptioin s = Observable.just(100, TimeUnit.Milliseconds)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.computation())
.subscribe(t -> decrementValue());
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();
        }
    }
}
私有静态类自动递减器实现可运行{
自动递减器(值选择器值选择器){
this.weakRef=新的WeakReference(valueSelector);
}      
@凌驾
公开募捐{
ValueSelector ValueSelector=(ValueSelector)weakRef.get();
如果(valueSelector==null){
返回;
}  
如果(valueSelector.Minus按钮被按下){
valueSelector.decrementValue();
valueSelector.mHandler.postDelayed(新的自动递减器(),重复间隔);
}否则{
valueSelector.mHandler.removeCallbacks(此选项);
Thread.currentThread().interrupt();
}
}
}

我没有检查任何错误。

它不会被破坏而导致内存泄漏,因为您的线程将强烈引用您的视图,从而引用您的活动

使内部类保持静态,并保持对run方法中所需变量的弱引用

您可以做的第二件事是中断您的线程,当您从窗口中分离视图时,如果线程被中断或未被中断,请检查run方法,但如果您的线程没有做太多工作,则不需要这样做

以下是您的runnable的外观

 Subscriptioin s = Observable.just(100, TimeUnit.Milliseconds)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.computation())
.subscribe(t -> decrementValue());
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();
        }
    }
}
私有静态类自动递减器实现可运行{
自动递减器(值选择器值选择器){
this.weakRef=新的WeakReference(valueSelector);
}      
@凌驾
公开募捐{
ValueSelector ValueSelector=(ValueSelector)weakRef.get();
如果(valueSelector==null){
返回;
}  
如果(valueSelector.Minus按钮被按下){
valueSelector.decrementValue();
valueSelector.mHandler.postDelayed(新的自动递减器(),重复间隔);
}否则{
valueSelector.mHandler.removeCallbacks(此选项);
Thread.currentThread().interrupt();
}
}
}

我没有检查任何错误。

它们从未被“销毁”。与Java中的任何其他对象实例一样,将在它们变得不可访问后的一段时间内收集垃圾。在这种情况下,,这可能是他们的线程停止运行后的一段时间。正常的内部类包括对顶级类的隐式引用,因此当活动被销毁时,仍然会存在引用,并且gc不会解决此问题,您需要使内部类成为静态的,还需要使用weakreference,并对长时间运行的作业和应用程序使用线程处理程序runOnUiThread方法你可以更新你的UIT,它们永远不会被“破坏”。与Java中的任何其他对象实例一样,将在它们变得不可访问后的一段时间内收集垃圾。在这种情况下,,这可能是他们的线程停止运行后的一段时间。正常的内部类包括对顶级类的隐式引用,因此当活动被销毁时,仍然会存在引用,并且gc不会解决此问题,您需要使内部类成为静态的,还需要使用weakreference,并对长时间运行的作业和应用程序使用线程处理程序runOnUiThread方法你可以更新你的ui它在代码中看起来怎么样?我已经将内部类设置为静态的,但是几乎所有的东西都需要变成静态的。此外,run()方法中使用的布尔值不能是WeakReference等,否则无法正常工作。谢谢顺便说一句,你提到的错误是什么?Cheersmeant不要复制和粘贴,使用这个想法,我很高兴它为您工作它在代码中看起来如何?我已经将内部类设置为静态的,但是几乎所有的东西都需要变成静态的。此外,run()方法中使用的布尔值不能是WeakReference等,否则无法正常工作。谢谢顺便说一句,你提到的错误是什么?啦啦队不要复制和粘贴,使用这个想法,我很高兴它为你工作