我试图理解Handler如何与Looper
配对,但我有一些问题。我需要在后台线程中执行一些长操作,然后在textView
中发送一些结果
按下按钮后出现以下错误:
只有创建视图层次结构的原始线程才能触及其视图。
public class MainActivity extends AppCompatActivity {
Button mButton;
TextView mTextView;
ConsumeThread mConsumeThread;
class ConsumeThread extends Thread{
public Handler mHandler;
@Override
public void run() {
Looper.prepare();
mHandler = new Handler(){
@Override
public void handleMessage(Message msg){
int arg = msg.what;
someLongOperation(arg);
}
};
Looper.loop();
}
private void someLongOperation(int arg){
// do some long operation
arg += 1000;
mTextView.setText("Operation's code is " +arg); // fatal exception
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.txt_view);
mButton = (Button) findViewById(R.id.button);
mConsumeThread = new ConsumeThread();
mConsumeThread.start();
mButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
if(mConsumeThread.mHandler != null){
Message msg = mConsumeThread.mHandler.obtainMessage(10);
mConsumeThread.mHandler.sendMessage(msg);
}
}
});
}
答案 0 :(得分:1)
获取主线程Handler
您已获得Handler
,如下所示。
因为: -
每个Handler实例都与一个线程和该线程的消息队列相关联。创建新的Handler时,它将绑定到创建它的线程的线程/消息队列
因此,您需要获得与Handler
相关联的MainThread
。为此,您可以使用以下之一: -
使用上下文
Handler mainHandler = new Handler(getMainLooper()){
@Override
public void handleMessage(Message msg) {
}
};
或直接使用Looper
即使没有Context
Handler mainHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
}
};
我认为你正在做一些长期运行的任务。如果你选择AsyncTask
,那就更好了。
答案 1 :(得分:1)
private void someLongOperation(int arg){
// do some long operation
arg =+ 1000;
mTextView.setText("Operation's code is " +arg); // fatal exception
}
//看到这里,你是工作线程,所以你不能有多余的UI工具包或者异常,所以如果你想在工作线程中做一些与ui相关的任务,请使用runOnUi,见这里
runOnUiThread(new Runnable() {
@Override
public void run() {
textview.setText("");
}
})
答案 2 :(得分:0)
您无法从其他线程更新UI。您必须将更新UI的代码移动到UIThread。
尝试使用:
runOnUiThread(new Runnable() {
@Override
public void run() {
//TextView Update Code
}
});
提示:尝试减少放在其中的代码行数,因为没有使用其他线程的目的。
答案 3 :(得分:0)
只有创建视图层次结构的原始线程才能触及其视图
你必须在主线程上做ui相关的工作...... 所以你可以这样做......
private void someLongOperation(int arg){
// do some long operation
arg =+ 1000;
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText("Operation's code is " +arg); // fatal exception
}
});
}