当一个程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件、用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程又被称为UI线程。
出于性能优化考虑,Android的UI操作不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题。为了解决这个问题,Android制定了一个简单的原则:只允许UI线程修改Activity里的UI组件,试图启动一个新线程并刷新UI是不允许的。那么如何让新线程可以刷新UI呢?为了解决这个问题,Android引入了Handler来处理解决这个问题。
Handler类的主要作用有两个:
- 在新启动的线程中发送消息
- 在主线程中获取、处理消息
package com.qicaiz.handlertest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity
{
TextView showTextView;
Button addButton;
MyHandler myHandler;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showTextView = (TextView)findViewById(R.id.showTextView);
addButton = (Button)findViewById(R.id.addButton);
<span style="color:#FF0000;">//在主线程中加入myHandler,当收到消息时会回调handleMessage(Message msg)方法</span>
myHandler = new MyHandler();
addButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View arg0)
{
// TODO Auto-generated method stu
MyThread myThread = new MyThread();
new Thread(myThread).start();
}
});
}
//定义一个新线程
class MyThread implements Runnable
{
@Override
public void run()
{
// TODO Auto-generated method stub
try
{
Thread.sleep(10000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("add", "更新UI");
msg.setData(bundle);
myHandler.sendMessage(msg); <span style="color:#FF0000;">//myHandler在新启动的线程中发送消息</span>
}
}
<span style="color:#FF0000;">//定义MyHandler 继承Handler并重写handleMessage(Message msg)方法</span>
class MyHandler extends Handler
{
//必须重写的方法
@Override
public void handleMessage(Message msg)
{
// TODO Auto-generated method stub
super.handleMessage(msg);
Bundle bundle = msg.getData();
String str = bundle.getString("add");
<span style="color:#FF0000;">//当收到消息时,刷新UI</span>
showTextView.setText(str);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}