Andy Strife Andy Strife - 11 days ago 6
Android Question

Clean Inner Class implementing Runnable

I have got a Class for a CustomView that has to inner Classes, both implement Runnable to do a Job in a separate Thread.

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


How to clean them up properly?
Do they get Destroyed automatically when the Activity hosting those CustomViews gets destroyed?

Cheers

Answer

It will not get destroyed causing a memory leak, as your thread will have a strong reference to your view, and hence your activity.

Make the inner class static and hold weak reference to variables you need in run method.

Second thing you can do is interrupt your thread , when you view get detached from the window and have check in the run method if thread got interrupted or not, though not necessary if your thread is not doing too much work.

Here is what your runnable should look like

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

I have not checked for any errors.