프로그래밍 언어/Android

Android "Only the original thread that created a view hierarchy can touch its views.."

Rateye 2021. 7. 2. 11:04
728x90
반응형

 

질문 : Android "Only the original thread that created a view hierarchy can touch its views.."

Android에서 간단한 음악 플레이어를 만들었습니다. 각 노래의보기에는 다음과 같이 구현 된 SeekBar가 포함됩니다.

public class Song extends Activity implements OnClickListener,Runnable {
    private SeekBar progress;
    private MediaPlayer mp;

    // ...

    private ServiceConnection onService = new ServiceConnection() {
          public void onServiceConnected(ComponentName className,
            IBinder rawBinder) {
              appService = ((MPService.LocalBinder)rawBinder).getService(); // service that handles the MediaPlayer
              progress.setVisibility(SeekBar.VISIBLE);
              progress.setProgress(0);
              mp = appService.getMP();
              appService.playSong(title);
              progress.setMax(mp.getDuration());
              new Thread(Song.this).start();
          }
          public void onServiceDisconnected(ComponentName classname) {
              appService = null;
          }
    };

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.song);

        // ...

        progress = (SeekBar) findViewById(R.id.progress);

        // ...
    }

    public void run() {
    int pos = 0;
    int total = mp.getDuration();
    while (mp != null && pos<total) {
        try {
            Thread.sleep(1000);
            pos = appService.getSongPosition();
        } catch (InterruptedException e) {
            return;
        } catch (Exception e) {
            return;
        }
        progress.setProgress(pos);
    }
}

이것은 잘 작동합니다. 이제 노래 진행의 초 / 분을 계산하는 타이머를 원합니다. 그래서 레이아웃에 TextView onCreate() 에서 findViewById() progress.setProgress(pos) 후에 run() 에 넣습니다.

String time = String.format("%d:%d",
            TimeUnit.MILLISECONDS.toMinutes(pos),
            TimeUnit.MILLISECONDS.toSeconds(pos),
            TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(
                    pos))
            );
currentTime.setText(time);  // currentTime = (TextView) findViewById(R.id.current_time);

그러나 마지막 줄은 예외를 제공합니다.

android.view.ViewRoot $ CalledFromWrongThreadException : Only the original thread that created a view hierarchy can touch its views..

SeekBar 수행하는 것과 동일한 작업을 수행 onCreate 에서 뷰를 생성 run() 에서 터치하면이 문제가 발생하지 않습니다.

답변

UI를 업데이트하는 백그라운드 작업 부분을 메인 스레드로 옮겨야합니다. 이를위한 간단한 코드가 있습니다.

runOnUiThread(new Runnable() {

    @Override
    public void run() {

        // Stuff that updates the UI

    }
});

Activity.runOnUiThread 문서.

백그라운드에서 실행중인 메서드 내부에이를 중첩 한 다음 블록 중간에 업데이트를 구현하는 코드를 복사하여 붙여 넣습니다. 가능한 한 적은 양의 코드 만 포함하십시오. 그렇지 않으면 백그라운드 스레드의 목적을 무시하기 시작합니다.

출처 : https://stackoverflow.com/questions/5161951/android-only-the-original-thread-that-created-a-view-hierarchy-can-touch-its-vi
728x90
반응형