2016-11-25 6 views
0

У меня есть класс для CustomView, который имеет внутренние классы, и реализовать Runnable для выполнения задания в отдельном потоке.Чистый внутренний класс, реализующий 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(); 
     } 
    } 
} 
} 

Как правильно их очистить? Получают ли они Разрушенные автоматически, когда действие, в котором находятся эти CustomViews, будет уничтожено?

Приветствия

+0

Они никогда не «разрушаются». После этого они получат сбор мусора после того, как они станут недоступными, как и любой другой экземпляр объекта в Java. В этом случае, вероятно, будет некоторое время после прекращения работы потока. – Andreas

+0

нормальный внутренний класс включает неявную ссылку на верхний класс, поэтому при уничтожении активности все еще будет существовать ссылка с этим, и gc не будет очищать эту проблему, вам нужно сделать внутренний класс static, а также использовать weakreference, а также использовать обработчик потока для длительных рабочих заданий и runOnUiThread метод u может обновить ваш ui –

ответ

1

Он не будет разрушаться, вызывая утечку памяти, так как ваш поток будет иметь сильный ссылку на ваш взгляд и, следовательно, вашу деятельность.

Сделать внутренний класс статическим и удерживать слабую ссылку на переменные, которые вам нужны в методе запуска.

Вторая вещь, которую вы можете сделать, это прервать вашу нить, когда вы просматриваете, отсоединяться от окна и проверять метод запуска, если поток был прерван или нет, но не нужен, если ваш поток не слишком много работает.

Вот что ваш работоспособным должен выглядеть

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

Я не проверяется на наличие ошибок.

+0

Как он выглядит в коде? Я поставил внутренние классы статическими, но тогда почти все должно стать статичным. Также логическое значение, используемое в методах run(), не может быть WeakReference и т. Д. Cheers –

+0

Кажется, что он работает нормально. Благодаря! Какие могут быть ошибки, упомянутые вами? Cheers –

+0

означает не копировать и вставлять, использовать идею, я рад, что это сработало для вас –

1

Нет, это вызовет ошибку, если активность будет уничтожен во время события таймера еще не завершено. Чтобы избежать этого, используйте WeakReference для некоторого объекта, уменьшающего значение. Но, как правило, это плохая практика - смешивать UI и некоторые лигические, потому что это сложно проверить. Рассмотрите возможность использования библиотеки rxJava, это будет выглядеть

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

в вашем методе OnPause() Отмена что actioin по

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