Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
559 views
in Technique[技术] by (71.8m points)

android - Android“只有创建视图层次结构的原始线程才能触摸其视图。”(Android “Only the original thread that created a view hierarchy can touch its views.”)

I've built a simple music player in Android.

(我已经在Android中构建了一个简单的音乐播放器。)

The view for each song contains a SeekBar, implemented like this:

(每首歌曲的视图都包含一个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);
    }
}

This works fine.

(这很好。)

Now I want a timer counting the seconds/minutes of the progress of the song.

(现在,我需要一个计时器来计算歌曲进度的秒/分钟。)

So I put a TextView in the layout, get it with findViewById() in onCreate() , and put this in run() after progress.setProgress(pos) :

(所以我将TextView放在布局中,在onCreate()使用findViewById()进行获取,然后将其放在progress.setProgress(pos)之后的run() progress.setProgress(pos) :)

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

But that last line gives me the exception:

(但是最后一行给我一个例外:)

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

(android.view.ViewRoot $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸其视图。)

Yet I'm doing basically the same thing here as I'm doing with the SeekBar - creating the view in onCreate , then touching it in run() - and it doesn't give me this complaint.

(但是,我在这里执行的操作基本上与在SeekBar执行的操作相同-在onCreate创建视图,然后在run()对其进行触摸-但这并没有给我这种抱怨。)

  ask by herpderp translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You have to move the portion of the background task that updates the UI onto the main thread.

(您必须将后台任务的更新UI的部分移到主线程上。)

There is a simple piece of code for this:

(为此,有一段简单的代码:)

runOnUiThread(new Runnable() {

    @Override
    public void run() {

        // Stuff that updates the UI

    }
});

Documentation for Activity.runOnUiThread .

(Activity.runOnUiThread文档。)

Just nest this inside the method that is running in the background, and then copy paste the code that implements any updates in the middle of the block.

(只需将其嵌套在后台运行的方法中,然后复制并粘贴实现代码更新的代码即可。)

Include only the smallest amount of code possible, otherwise you start to defeat the purpose of the background thread.

(仅包含尽可能少的代码,否则您将无法达到后台线程的目的。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...