Android的"只有创建视图层次可以触摸其观点和QUOT原来的线程; [英] Android "Only the original thread that created a view hierarchy can touch its views."

查看:244
本文介绍了Android的"只有创建视图层次可以触摸其观点和QUOT原来的线程;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经建立了一个简单的音乐播放器的Andr​​oid。该视图为每首歌曲包含一个搜索栏,这样实现的:

I've built a simple music player in Android. The view for each song contains a SeekBar, implemented like this:

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布局,让它使用findViewById()中的onCreate(),和progress.setProgress(POS)之后,把这个在run():

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

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.

不过,我做基本上是同样的事情,在这里为我做的搜索栏 - 创造的onCreate视图,然后轻触它的run() - 它并没有给我这样的抱怨。那么,有一个明显的错误吗?我是新来的Andr​​oid和Java的,所以我不会感到惊讶,如果它的一些愚蠢的。

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. So is there an obvious mistake here? I'm new to both Android and Java, so I won't be surprised if it's something dumb.

推荐答案

您必须移动,更新用户界面到主线程的后台任务的一部分。有一个简单的一块$ C $下这样的:

You have to move the portion of the background task that updates the ui onto the main thread. There is a simple piece of code for this:

runOnUiThread(new Runnable() {
     @Override
     public void run() {

//stuff that updates ui

    }
});

文档<一个href="http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)"><$c$c>Activity.runOnUiThread

就在鸟巢这是在后台运行的方法内,然后复制粘贴code实现在块的中间任何更新。包括code可能只有最小的量,否则你就打败了后台线程的目的。

Just nest this inside the method that is running in the background, 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.

这篇关于Android的&QUOT;只有创建视图层次可以触摸其观点和QUOT原来的线程;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆