异常信息:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
必须在程序的主线程(UI)中更新界面显示
如下代码:
public class BActivity extends Activity {
private Button mBtn1_bpage;
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
//初始化控件
mBtn1_bpage = (Button) findViewById(R.id.btn1_bpage);
mTextView = (TextView) findViewById(R.id.tv1_bpage);
//设置监听
mBtn1_bpage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeText();
}
});
}
/**
* 改变文本
*/
private void changeText() {
new Thread(new Runnable() {
@Override
public void run() {
mTextView.setText("标题!");
}
}).start();
}
}
运行,程序崩溃。
有时会碰到在非主线程更新视图的需要,有两种处理的方式,一种是Handler,另一种是Activity中的runOnUiThread(Runnable)方法。
方法1:使用Handler
public class BActivity extends Activity {
private Button mBtn1_bpage;
private TextView mTextView;
Handler mHandler = new Handler() {
//接受子线程的消息机制
@Override
public void handleMessage(Message msg) {
int what=msg.what;
switch (what){
case 102:
//改变页面的文字
mTextView.setText("改变文字");
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
//初始化控件
mBtn1_bpage = (Button) findViewById(R.id.btn1_bpage);
mTextView = (TextView) findViewById(R.id.tv1_bpage);
//设置监听
mBtn1_bpage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeText();
}
});
}
/**
* 改变文本
*/
private void changeText() {
new Thread(new Runnable() {
@Override
public void run() {
// mTextView.setText("标题!");
mHandler.sendEmptyMessage(102);
}
}).start();
}
}
方法2:使用runOnUiThread(Runnable)方法
//设置监听
mBtn1_bpage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// changeText();
runOnUiThread(new Runnable() {
@Override
public void run() {
//改变页面的文字
mTextView.setText("改变文字2");
}
});
}
});
方法3:使用AsyncTask
public class BActivity extends Activity {
private Button mBtn1_bpage;
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
//初始化控件
mBtn1_bpage = (Button) findViewById(R.id.btn1_bpage);
mTextView = (TextView) findViewById(R.id.tv1_bpage);
//设置监听
mBtn1_bpage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyAsyncTask myAsyncTask=new MyAsyncTask();
myAsyncTask.execute();
}
});
}
private class MyAsyncTask extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... params) {
publishProgress();
return null;
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
//改变页面的文字
mTextView.setText("改变文字3");
}
@Override
protected void onPostExecute(Void result) {
//改变页面的文字
mTextView.setText("改变文字3_2");
super.onPostExecute(result);
}
}
三个方法:
- onProgressUpdate方法的执行在收到publishProgress方法调用后,运行在UI线程中,对UI控件进行处理。
- onPostExecute()方法,则在doInBackground()方法结束后运行在UI线程,对result进行处理
- doInBackground()方法中,就是在后台线程中处理异步任务,不能做Toast操作,否则出现异常。
以上是根据我的一些理解,做的总结分享,旨在抛砖引玉,希望有更多的志同道合的朋友一起讨论学习,共同进步!
网友评论