Handler机制学习
- handler的由来
当程序第一次启动时,Android会同时启动一条主线程(Main Thread)来负责处理与UI相关的事件,我们也将其称为“UI线程”。处于性能优化考虑,Android的UI操作并不是线程安全的,意味着如果多个线程并发操作UI线程,可能导致线程安全问题。
为了解决多线程问题——Android平台只允许UI线程修改Activity里的UI组件,就会导致新启动的线程无法改变界面组建的属性值。而如果我们把所有工作都放在主线程里,则会抛出ANR异常。
所以,Handler机制应运而生。其设计思路为:
把一些比较长的消息,放在一个单独的线程里面处理,把处理以后的结果,返回给主线程运行,通过Handler来进行二者间的通信。 - Handler的作用
- 在新启动的线程中发送消息。使用Handler对象的sendMessage()方法或者sendEmptyMessage方法发送消息。
- 在主线程中获取处理消息。重写Handler类中处理消息的方法(void handlerMessage(Message msg)),当新启动的线程发送消息时,消息发送到与之关联的MessageQueue。而Handler不断地从MessageQueue中获取并处理消息。
- Handler的使用与运作流程
- 首先需要进行Handler声明,覆写handleMessage方法(放在主线程中)
- 子线程发送Message给UI线程表示自己任务已经执行完成,主线程可以做相应的操作。
- 运作流程:
- Handler三大角色
- Handler:处理者,负责发送和处理消息
发送消息,把消息发送给Looper管理的MessageQueue
处理消息,负责处理Looper分发给它的消息 - MessageQueue和Message:消息的载体,Handler接收和处理的消息对象。
- Looper:每个线程只有一个Looper,它负责管理对应的MessageQueue,会不断地从MessageQueue中取出消息,并将消息分发给对应的Handler处理。
- 基于Handler Post()方法的小Demo
- activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.wangli.handlerdemo.MainActivity">
<ProgressBar
android:id="@+id/progressBar1"
android:max="100"
android:progress="0"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="当前进度为:0"/>
<Button
android:id="@+id/button_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start"/>
</LinearLayout>
- MainActivity.java
package com.example.wangli.handlerdemo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
ProgressBar pb;
TextView tv;
Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pb = (ProgressBar) findViewById(R.id.progressBar1);
tv = (TextView)findViewById(R.id.textView);
Button btn = (Button) findViewById(R.id.button_start);
btn.setOnClickListener(new View.OnClickListener(){
int i = 0;
@Override
public void onClick(View v){
//开启一个新线程
new Thread(){
public void run(){
while (i < 100){
//将线程添加到消息队列
handler.post(new Runnable(){
public void run(){
//更新UI
pb.setProgress(i++);
tv.setText("当前进度:"+ i);
}
});
//线程睡眠
try{
Thread.sleep(200);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}.start();
}
});
}
}
- 运行效果图
- 基于Handler sendMessage()
package com.example.wangli.handlerdemo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
ProgressBar pb;
TextView tv;
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int progress = msg.what;
pb.setProgress(progress);
tv.setText("当前进度为:"+progress);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pb = (ProgressBar) findViewById(R.id.progressBar1);
tv = (TextView)findViewById(R.id.textView);
Button btn = (Button) findViewById(R.id.button_start);
btn.setOnClickListener(new View.OnClickListener(){
int i = 0;
@Override
public void onClick(View v){
//开启一个新线程
new Thread(){
public void run(){
while (i < 100){
Message msg = Message.obtain();
msg.what = i++;
handler.sendMessage(msg);
//线程睡眠
try{
Thread.sleep(200);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}.start();
}
});
}
}