简单的介绍Handler(一)
- 很高兴和大家再次见面,我是lady_zhou,这是我的Blog,欢迎大家一起来学习Handler
1.1 Handler怎么使用
下面是一段更新TextView内容的代码:
public class MainActivity extends Activity {
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
new Thread(){
public void run() {
try {
Thread.sleep(3000);
mTextView.setText("update thread");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
};
}.start();
}
}
如果这样写,一定会出现,我们熟悉的界面:
可以看的LogCat中的报错信息:
这个信息告诉我们在非UI线程中更新UI了,这个是不允许的。
那怎么办?当然用Handler啊!
private TextView mTextView;
private Handler mHandler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
new Thread(){
public void run() {
try {
Thread.sleep(3000);
mHandler.post(new Runnable() {
@Override
public void run() {
mTextView.setText("update thread");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
}
}
这里使用了post(Runnable)方法。
来看一下sendMessage方法,主要是发送消息,简单举一个传一个参数的例子:
public class MainActivity extends Activity {
private TextView mTextView;
private Handler mHandler=new Handler(){
public void handleMessage(android.os.Message msg) {
//用msg取出arg1的参数,arg1是Int型
mTextView.setText(""+msg.arg1);
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
new Thread(){
public void run() {
try {
//休眠3秒
Thread.sleep(3000);
Message message = new Message();
message.arg1=100;
mHandler.sendMessage(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
}
}
这里只是举了一个参数的例子,但是常见的并不是传一个参数这么简单,而是多个参数的传入,比如通过网络获取的以json格式封装的数据,遇到这种情况,就必须转化成对应的实体数据:
public class MainActivity extends Activity {
private TextView mTextView;
private Handler mHandler=new Handler(){
public void handleMessage(android.os.Message msg) {
mTextView.setText(""+msg.obj);
};
};
/**
* 这里是一个“书”类,包含了两个属性:作者和书名
* @author ztt
*
*/
class Book{
public String author;
public String bookName;
public String toString(){
return "author="+author+","+"bookName="+bookName;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
new Thread(){
public void run() {
try {
Thread.sleep(3000);
//复用系统的message,可以返回message对象
Message message = mHandler.obtainMessage();
Book book = new Book();
book.author = "上野宣";
book.bookName = "图解HTTP";
message.obj = book;
mHandler.sendMessage(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
}
}
简单的介绍了Handler的两种方法,还有sendMessageDelayed、postDelayed这两种方法,那为什么要设计只能通过Handler机制更新呢?
他最根本的目的就是解决多线程并发问题
1.2 Handler、Looper、MessageQueue
Handler就是一个消息处理器,将消息投递给消息队列,然后在由对应的线程从消息队列中逐个去除消息,并且执行。默认情况下,消息队列只有一个,即主线程的消息队列。
Looper通过Looper.prepare()来创建Looper对象(消息队列封装在Looper对象中),并且保存在sThreadLoal中,然后通过Looper.loop()来执行消息循环,通常会成对出现。
MessageQueue就是一个消息队列,可以添加消息,并且处理消息
Handler需要跟Looper进行关联
总结一下就是:handler负责发送消息,Looper负责接收Handler发送的消息,并直接把消息回传给Handler自己,MessageQueue就是一个存储消息的容器。