在前面的几篇文章中,不管是AsyncTAsk方式,亦或是new一个Runable,都没有涉及UI界面的更新(),今天在进行注册反馈注册信息的时候,就发生了ViewRootImpl$CalledFromWrongThreadException异常,究其原因是因为android中的view和和控件不是线程安全的。
为此android已入了Handler消息传递机制,来实现在新建的线程中操作UI界面。
信息处理类(Handler)允许发送和处理Message或Runable对象到其所在线程的MessageQuene中。Handler主要有以下作用:
(1)将Message或Runable应用Post() 或 sendMessage() 方法发送到MessageQuene中,在发送是可以指定延迟时间,发送时间及要携带的Bundle数据,当MessageQuene循环到该Message时,调用相应的Handler对象的HandlerMessage()方法对其进行处理。
(2)在子线程与主线程进行通信,也就是在工作线程中与UI线程进行通信。
补充:在android中,一个线程对应一个Looper对象,而一个Looper对象又对应一个MessageQuene(消息队列,用于存放Message消息,MessageQuene封装在Looper中),在主线程中,系统会自动为主线程创建Looper对象,并开启消息循环,但在非主线程创建Handler对象(不加Looper.prepare()和Looper.Loop()方法来初始化一个Looper对象),会报Can't create handler inside thread that has not called Looper.prepare()错误。
从飞天开放平台获取注册数据的简单代码:
package com.example.alitest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import ECSConnecter.SigninConnecter;
import XMLReader.SigninData;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity implements Runnable {
private Button button;
private Handler handler;
private TextView name;
private TextView pwd;
private EditText etName;
private EditText etPwd;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Thread t = new Thread(MainActivity.this); //创建新线程
t.start(); //开启线程
handler = new Handler() { //这个handler发送的Message会被传递给主线程的MessageQueue。
public void handleMessage(Message msg) { //回调
if (msg.what == 1) {
name.setText(msg.getData().getString("result"));
pwd.setText(msg.getData().getString("ID"));
}
super.handleMessage(msg);
}
};
}
});
}
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
/*
* 连接注册进程
*/
Map<String, String> map = new HashMap<String, String>();
map.put("name", etName.getText().toString());
map.put("password", etPwd.getText().toString());
SigninConnecter signconn = new SigninConnecter(map);
try {
signconn.getXML();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
signconn.readXML();
SigninData data = signconn.getData();
Message m = handler.obtainMessage(); //获取一个Message
Bundle bundle = new Bundle(); //获取Bundle对象
m.what = 1; //设置消息标识
bundle.putString("result", data.getResult());
bundle.putString("ID", data.getId()); //保存数据
m.setData(bundle); //将Bundle对象保存到Message中
handler.sendMessage(m); //发送消息
}
}
/*
* 初始化控件
*/
private void initView() {
name = (TextView) findViewById(R.id.textView1);
pwd = (TextView) findViewById(R.id.textView2);
etName = (EditText) findViewById(R.id.etName);
etPwd = (EditText) findViewById(R.id.etPwd);
button = (Button) findViewById(R.id.button);
}
}
像所有的android通信方法一样,别忘了打开internet的权限~