Handler作为Android中举足轻重的知识点,无论是在实际开发还是在面试中都经常会用到,并且在网上关于Handler的讲解不胜枚举,本人深知水平有限,因此仅在此做一下自己的小结,权当学习中的笔记。
之前写过一篇有关Handler中基本方法使用的一篇文章http://blog.csdn.net/james_shu/article/details/53367035,本篇基于此,写出一些其他的新内容。
Android中的异步消息处理主要由4个部分组成:Message、Handler、MessageQueue和Looper。其中,
Message:Message是在线程之间传递的消息,当我们在不同的线程中传递数据时,Handler将我们要传递的信息封装到Message中然后进行传递。
Handler:Handler主要是用于发送消息,接受并处理消息。
MessageQueue:消息队列,它主要用于存放Handler发送的消息。存放于消息队列中的消息等待被处理,每一个线程中只会有一个MessageQueue对象。
Looper:Looper是每一个线程中的MessageQueue的管家,调用Looper的loop()方法之后就会进入到一个无限循环中,然后当发现MessageQueue中存在一条消息就会将其取出并将这条消息传递到Handler的handleMessage()方法,每一个线程中只会有一个Looper对象。
这里应该提到的一点是:
主线程中默认初始化了Looper,因此我们可以在创建Handler之后直接发送消息和处理消息,其中处理消息一定是创建Handler所在的线程中处理消息,而发送消息就可以在不同的线程中发送消息。
当我们创建一个新的线程的时候(不在主线程时),此时我们如果需要在新线程中创建Handler作为其他线程与所创建的当前线程的通信的桥梁时,我们需要首先创建Looper对象,然后创建Handler对象。
下面我们以计算指定区间的质数为例来介绍在新线程中创建Handler的用法:
布局文件:
<EditText
android:id="@+id/etNum"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:onClick="calculate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="点击得到处理的结果"
/>
代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
calThread=new CalThread();
calThread.start();
}
private void initView() {
etNum= (EditText) findViewById(R.id.etNum);//使用Handler将用户在UI界面输入的数值上限动态的传递给新启动的线程
}
class CalThread extends Thread{
public Handler mHandler; //在新线程中创建Handler,作为主线程与新线程的通信的桥梁
//在主线程中系统已经初始化了一个Looper对象,因此程序可以直接创建handler对象然后使用创建的Handler对象来发送消息和处理消息
//然而当自己创建一个新的线程的时候,为了使用自己创建的Handler对象,此时就应该自己同时创建一个Looper对象,此时Handler的功能才算是完整的
@Override
public void run() {
super.run();
Looper.prepare();
mHandler=new Handler(){
//定义处理消息的方法
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what==0x123){
int upper=msg.getData().getInt(UPPER_NUM);
List<Integer> nums=new ArrayList<Integer>();
//计算从二开始的质数
outer:
for (int i=2;i<=upper;i++){
for (int j=2;j<=Math.sqrt(i);j++){
if(i!=2&&i%j==0){
continue outer;
}
}
nums.add(i);
}
Toast.makeText(MainActivity.this,nums.toString(),Toast.LENGTH_SHORT).show();
}
}
};
Looper.loop();
}
}
public void calculate(View view){
Message msg=new Message();
msg.what=0x123;
Bundle bundle=new Bundle();
bundle.putInt(UPPER_NUM,Integer.parseInt(etNum.getText().toString()));
msg.setData(bundle);
calThread.mHandler.sendMessage(msg);
}