当在Android App的非UI线程中执行UI更新操作时,就会抛出WrongThreadException异常。该异常的原因是UI更新应该是在UI线程中完成的,而Android系统又是单线程模型的,意味着只有UI线程有权访问UI组件。因此,当想要更新UI组件内容时,必须确保这个更新操作是在UI线程中执行的。
下面是两个示例说明,解释WrongThreadException异常的原因和如何解决:
示例一:
new Thread(new Runnable() {
@Override
public void run() {
// 在非UI线程中执行以下操作
TextView textView = findViewById(R.id.text_view);
textView.setText("Hello World!"); // 抛出WrongThreadException
}
}).start();
在这个示例中,我们在一个新的线程中更新了UI组件TextView
的内容,但是由于我们在非UI线程中执行了UI更新操作,导致抛出了WrongThreadException异常。
为了解决这个问题,我们可以使用Android提供的Handler
类,在UI线程中执行我们想要更新的UI操作。修改代码如下:
new Thread(new Runnable() {
@Override
public void run() {
// 在非UI线程中执行以下操作
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
TextView textView = findViewById(R.id.text_view);
textView.setText("Hello World!");
}
});
}
}).start();
在这个示例中,我们创建了一个Handler
对象,在它的post()
方法中创建了一个新的Runnable
对象,用于在UI线程中执行UI更新操作。这样我们就避免了在非UI线程中直接更新UI组件引起的异常。
示例二:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 在监听器中的非UI线程中执行以下操作
new Thread(new Runnable() {
@Override
public void run() {
// 在非UI线程中执行以下操作
TextView textView = findViewById(R.id.text_view);
textView.setText("Hello World!"); // 抛出WrongThreadException
}
}).start();
}
});
}
在这个示例中,我们在OnClickListener
的回调方法中创建了一个新的线程,用于更新UI组件。由于该回调方法运行在UI线程中,但是更新UI组件的线程是一个新的非UI线程,又会引发WrongThreadException异常。
为了解决这个问题,我们可以使用和上述示例一样的方法,在新线程中使用Handler
在UI线程中执行UI更新操作。代码修改如下:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 在监听器中的非UI线程中执行以下操作
new Thread(new Runnable() {
@Override
public void run() {
// 在非UI线程中执行以下操作
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
TextView textView = findViewById(R.id.text_view);
textView.setText("Hello World!");
}
});
}
}).start();
}
});
}
在这个示例中,我们使用了和上面的方法一样的方式,将UI更新操作放到了Handler的post()
方法中,在UI线程中执行更新操作,避免了在非UI线程中更新UI组件引起的异常。