直接在UI线程中开启子线程来更新TextView显示的内容,运行程序我们会发现,错 误android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.翻译过来就是:只有创建这个控件的线程才能去更新该控件的内容。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。
在Android开发中,为了UI线程能及时响应需要避免在其中执行耗时操作,以防止界面假死甚至ANR。我们一般把耗时操作如下载,查询放在一个单独的线程中。这之后再将结果更新到UI界面。android平台在非UI线程中更新界面大致有以下几种方式
Handler的处理过程运行在创建Handler的线程里
一个Looper对应一个MessageQueue
一个线程对应一个Looper
一个Looper可以对应多个Handler
子线程中修改UI的方法
要想修改UI都必须在主线程中去做,我们不能直接在UI线程中去创建子线程,要利用消息机制:handler.
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。
在Android开发中,为了UI线程能及时响应需要避免在其中执行耗时操作,以防止界面假死甚至ANR。我们一般把耗时操作如下载,查询放在一个单独的线程中。这之后再将结果更新到UI界面。android平台在非UI线程中更新界面大致有以下几种方式
Handler的处理过程运行在创建Handler的线程里
一个Looper对应一个MessageQueue
一个线程对应一个Looper
一个Looper可以对应多个Handler
不确定当前线程时,更新UI时尽量调用post方法
<span style="color:#333333;">public class MainActivity extends Activity {
private Button button;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new TimerHandler();
WorkerThread wt = new WorkerThread();
wt.start();
}
class WorkerThread extends Thread{
@Override
public void run(){
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//创建消息
Message msg = handler.obtainMessage();
msg.arg1 = 10;
msg.arg2 = 20;
msg.obj = "zhangsan";
//发送消息
handler.sendMessage(msg);
}
}
}
class TimerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
//接收消息,此消息可以使对象
int i = msg.arg1;
int j = msg.arg2;
String s = (String)msg.obj;
Log.d("Handler", "收到消息:arg1:" + i +",arg2:" + j + ",s:" + s);
}
}
}</span>
一些耗时间的操作放在线程中去,通过Handler传递消息
public class MainActivity extends Activity {
private TextView textView;
private Button button;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new NetworkHandler();
textView = (TextView)findViewById(R.id.textViewId);
button = (Button)findViewById(R.id.buttonId);
button.setOnClickListener(new ButtonListener());
}
class ButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
NetworkThread nt = new NetworkThread();
nt.start();
}
}
class NetworkThread extends Thread{
@Override
public void run(){
String url = "http://192.168.105.129:8081/data.html";
Log.d("Handler02", "准备访问网路");
//得到从网上下载的数据
String data = getStringFromNetwork(url);
//textView.setText(data);该行代码引起错误的原因是,不能够在Worker Thread当中修改控件的值
//把数据放到handler中要用handler.obtainMessage();
Message msg = handler.obtainMessage();
msg.obj = data;
handler.sendMessage(msg);
}
}
class NetworkHandler extends Handler{
@Override
public void handleMessage(Message msg){
//得到handler中数据把它赋给data
String data = (String)msg.obj;
textView.setText(data);
}
}
//新建一个类,类型是String url
public String getStringFromNetwork(String url){
String result = "";
//建个Http客户端访问网络下载数据
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = httpClient.execute(httpGet);
if(response.getStatusLine().getStatusCode() == 200){
HttpEntity entity = response.getEntity();
//连接已建立数据在entity中从entity中开始读数据
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));
result = reader.readLine();
Log.d("Handler02", "访问网络的结果是" + result);
return result;
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
Looper的用法
class WorkerThread extends Thread{
@Override
public void run(){
//生成Looper对象,该对象与当前线程对象组成了对应关系
Looper.prepare();
//生成Handler对象,并将其与刚刚生成Looper对象建立对应关系
handler = new Handler(){
@Override
public void handleMessage(Message msg){
Log.d("Handler", "收到来自主线程的消息");
}
};
Looper.loop();
}
}
子线程中修改UI的方法
class WorkThread extends Thread{
int i = 0 ;
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
handler.post(new Runnable() {
@Override
public void run() {
textView.setText(i + "");
}
});
}