обновление пользовательского интерфейса из обработчика в другом Runnable

У меня проблема с чем-то, что должно работать как таймер. Я прочитал эту статью в соответствии с использованием «таймера» в Android: http://developer.android.com/resources/articles/timed-ui-updates.html

У меня есть TextView и ImageView в моем макете. У меня есть AnimationDrawable в этом ImageView. Я переопределил класс AnimationDrawable, потому что хочу знать, когда моя анимация будет завершена. Однако runnable, который я хочу вызвать, когда моя анимация закончилась, работает правильно. Но в случае, когда я хочу обновлять TextView каждую секунду, другой runnable (в приведенном ниже коде) вызывается только один раз (я вижу число «1» во время всей анимации).

TextView timeFlow;
int seconds;

private Runnable mUpdateTimeTask = new Runnable() {
       public void run() {            
           seconds++;             
           timeFlow.setText(String.valueOf(seconds));          
       }
};

private void startAnimation() {      
    image = (ImageView) this.findViewById(R.id.image);      
    recordImage.setBackgroundResource(R.drawable.record_animation);
    timeFlow = (TextView) this.findViewById(R.id.time_flow);
    timeFlow.setText("...");            

    image.post(new Runnable() { 
    @Override
    public void run() {
        CustomAnimationDrawable currentAnimation = new CustomAnimationDrawable((AnimationDrawable) recordImage.getBackground());
        currentAnimation.setOnFinishCallback(runnable);
        recordImage.setBackgroundDrawable(currentAnimation);
        currentAnimation.start();                               

        handler.removeCallbacks(mUpdateTimeTask);
        handler.postDelayed(mUpdateTimeTask, 100);                                          
        }
    });     
}

person woyaru    schedule 29.07.2011    source источник


Ответы (1)


Вы не можете вызвать метод пользовательского интерфейса из рабочего потока. Вместо этого вам нужно изменить код в mUpdateTimeTask на

private Runnable mUpdateTimeTask = new Runnable() {
    public void run() {            
         seconds++;             
         timeFlow.post(new Runnable() {
               timeFlow.setText(String.valueOf(seconds));
         });
         // It's not clear if handler is accessible here, but you get the picture.
         handler.postDelayed(mUpdateTimeTask, 100); 
    }
};

Раздел Рабочий поток в руководстве для разработчиков Android. имеет больше примеров.

person Jason    schedule 29.07.2011
comment
О, и не забудьте вызвать handler.postDelayed(mUpdateTimeTask, 100); в конце вашего метода run(). Handler.postDelayed — одноразовый выстрел. Я отредактирую свой ответ, чтобы отразить это. - person Jason; 29.07.2011
comment
Спасибо, это действительно работает. Но у меня пока есть одна проблема. Моя анимация завершилась, runnable — AnimationDrawable OnFinishCallback — был вызван, но таймер все еще работает. Я думаю, что это должно остановиться, когда моя анимация остановилась. - person woyaru; 30.07.2011
comment
О, это было так просто, только использовать handler.removeCallbacks(mUpdateTimeTask); в runnable, вызываемом после завершения AnimationDrawable. - person woyaru; 30.07.2011