我有一个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();
这是影响此textview的所有代码。有什么想法吗?
答案 0 :(得分:2)
您正在尝试更新后台UI
上的Thread
。那不是不。您需要使用runOnUiThread()或AsyncTask或Handler
像
这样的东西 runOnUiThread(new Runnable() {
public void run()
{
tvCurrentBeat.setText("Current Beat: ");
}
});
}
您可能还想阅读Painless Threading
答案 1 :(得分:2)
这是影响此textview的所有代码。有什么想法吗?
在Android中有限制告诉您,您只能从其原始线程操纵UI元素(正如@Delyan在评论中指出的那样)。
您创建了与主(UI)线程不同步的工作者(后台)线程,并且不允许更新UI(出于安全性和平稳运行的原因)
您可以选择如何实现目标:
所有提到的结构都是同步的,或者提供与UI线程同步的方法,并允许使用UI进行操作。
答案 2 :(得分: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();