0

我有一个 textView(称为 tvCurrentBeat),每当我尝试使用 setText() 时,我的应用程序都会在启动时崩溃。如果我删除这行代码,应用程序将正常运行。

XML 代码:

<TextView
      android:id="@+id/tvCurrentBeat"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignLeft="@+id/ivDividerMiddle"
      android:layout_below="@+id/ivDividerMiddle"
      android:layout_marginTop="10dp"
      android:text="Current Beat:"
      android:textColor="#ffffff"
      android:textAppearance="?android:attr/textAppearanceLarge" />

变量初始化:

tvCurrentBeat = (TextView) findViewById(R.id.tvCurrentBeat);

其他代码:

new Thread() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();

            while (true) {
                if (metronomeOn) {
                    metronome = new Metronome(10000);
                    metronome.play();
                    metronomeOn = false;
                }
                tvCurrentBeat.setText("Current Beat: ");
            }
        }

    }.start();

这是影响这个文本视图的所有代码。有任何想法吗?

4

3 回答 3

2

这是影响这个文本视图的所有代码。有任何想法吗?

在 Android 中,有一个限制告诉您只能从它们的原始线程中操作 UI 元素(正如@Delyan 在评论中指出的那样)。

您创建了与主 (UI) 线程不同步且不允许 UI 更新的工作线程(后台)(出于安全和平稳运行的原因)

您有几种选择如何实现您的目标:

  • runOnUiThread() 的用法
  • 处理程序
  • 异步任务

所有提到的结构都是同步的,或者提供了与 UI 线程同步的方法,并允许使用 UI 进行操作。

于 2013-08-02T23:37:40.240 回答
2

您正在尝试UI在背景上更新Thread。那是不行的。您需要使用runOnUiThread()AsyncTaskHandler

就像是

 runOnUiThread(new Runnable() {
        public void run()
        {
           tvCurrentBeat.setText("Current Beat: ");
        }
    });
}

您可能还想阅读无痛线程

于 2013-08-02T23:34:44.147 回答
1

您不能从后台线程更新 UI 元素。您需要创建一个 Runnable 并通过它更新它们。尽管还有其他选项可以做到这一点,但这是我最常使用的选项。

这是一个例子:

private Handler threadHandler = new Handler();

// ...

while (true) {
    if (metronomeOn) {
        metronome = new Metronome(10000);
        metronome.play();
        metronomeOn = false;
    }
    threadHandler.post(updateRunnable);
}

// ...

final Runnable updateRunnable = new Runnable() {
    public void run() {
        tvCurrentBeat.setText("Current Beat: ");
    }
}; 

另一种方法是使用runOnUiThread()它只在主线程上运行你的东西。

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();

        while (true) {
            if (metronomeOn) {
                metronome = new Metronome(10000);
                metronome.play();
                metronomeOn = false;
            }
            tvCurrentBeat.setText("Current Beat: ");
        }
    }
}.start();
于 2013-08-02T23:36:06.550 回答