Android的"只有创建视图层次可以触摸其观点和QUOT原来的线程;视图、线程、层次、观点

由网友(遥远星河)分享简介:我已经建立了一个简单的音乐播放器的Andr​​oid。该视图为每首歌曲包含一个搜索栏,这样实现的:I've built a simple music player in Android. The view for each song contains a SeekBar, implemented like this:...

我已经建立了一个简单的音乐播放器的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

    }
});

文档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.

阅读全文

相关推荐

最新文章