前一段时间跟着同学共同开发过几个项目,但是那都是照搬别人的代码,真正自己撸出来的代码还是少数,就比如说现在要说的Handler,更多的是在需要使用的时候百度搜搜资料,或者是在《第一行代码》上面直接拿来用,所以呢,感觉如果自己要进阶的话,就不能这样一直copy代码,对待安卓的每一个知识点都要自己深刻解才行,这样在以后的开发中才会更加的得心应手,才能处理出现的各种问题。
首先来说说我对Handler的理解,Handler在辞典中的翻译是处理者的意思,所以我们可以将它理解为发送和处理消息的人,在Java中,你的每一个功能基本上都是通过某一个或者是某几个方法来共同实现了,Handler的功能也不例外,发送消息一般都是通过sendMessage()来实现的,但是发出消息之后,最后又是怎么能够处理这个经过一理解加工处理之后的数据的呢?这里Handler又提供了一个方法,handleMessage(),这个方法是用来最后接受上述数据的。Handler的主要原理就是上面的内容,内容不多,但是内部是怎么个运行机制呢?在这里要介绍一下安卓的异步消息处理机制,我们都知道,安卓内部是时时刻刻都运行着多线程的,多线程之间肯定要进行相应的信息交互,最为典型的就是安卓不能在子线程中更新UI。上代码:
public void onClick(View v) {
switch (v.getId()) {
case R.id.Click:
new Thread() {
// 重写run()方法
public void run() {
click.setText("你点击过了");
}
}.start();
break;
}
}
上面是onclick()方法中的代码,再来看看xml文件中的代码,这个比较简单,就是定义一个控件即可
<Button
android:id="@+id/Click"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="点击变换文字" />
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch
下图是运行到模拟器上面的错误显示,在点击了按钮之后,程序直接崩溃。
那么上面的错误到底是如何产生的呢,,,最重要的原因是安卓并不是线程安全的,直观的理解就是不能在子线程中更新UI,那么如果我们需要在子线程中去执行一些耗时的任务,然后进行UI更新的时候我们该怎么办呢,这时候handler的作用就显示出来了,如上所述,Handler就是用来进行线程之间的消息传递的,所以这里我们可以将子线程中改变的信息通过Handler传递到主线程中就可以了,整个代码贴出来
package com.example.handler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewDebug.FlagToString;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private Button click;
public static final int Flag = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
click = (Button) findViewById(R.id.Click);
click.setOnClickListener(this);
}
// 创建一个Handler对象,用handleMessage()方法接收信息,最后在主线程中更新UI
private Handler handler = new Handler() {
public void handleMessage(Message message) {
switch (message.what) {
case Flag:
click.setText("你好,你点击过我了");
break;
default:
break;
}
}
};
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.Click:
new Thread() {
// 重写run()方法
public void run() {
/**
* new一个message对象 obtmessage
* 通过hangdler的sendmessage()方法将这个对象发送出去,然后在主线程中的Handler中接受数据
*/
Message obtMessage = new Message();
obtMessage.what = Flag;
handler.sendMessage(obtMessage);
}
}.start();
break;
}
}
}
很简单的代码,最终终于实现了想要的功能。探究安卓内部的运行机制,在安卓内部,有用于存放handler发送的消息,即消息队列MessageQueue(),每次有需要用的信息,就直接通过调用Loop的loop()方法,就会将MessageQueue中的消息发送到handleMessage()方法中,然后判断其的what字段,如上代码所示,最后就能进行相应的操作,以上。