Handler的定义
主要接受子线程发送的数据, 并用此数据配合主线程更新UI。 在平时的安卓开发过程中,Handler一定不少见,Handler是Android消息机制的上层接口,这使得在开发过程中只需要和Handler交互即可。很多人认为Handler的作用就是更新UI,的确没错,但是更新UI仅仅是Handler的一个特殊的使用场景。
为什么要使用Handler
我们有时候需要在子线程做一些耗时操作,比如说访问网络或者耗时的I/O操作,当这些耗时操作完成时,程序的UI进行相应的改变。由于安卓开发规范的限制,我们不能在子线程中访问UI控件,因为UI的控件是线程非安全的,这个时候通过Handler就可以将更新UI的操作切换到主线程中执行
Looper的介绍
Looper我们称为循环器,它是连接Message Queue和Handler之间桥梁的角色。
它的作用是不断的接受Message Queue的Message,然后派发给相应的Handler。
Looper中存放有MessageQueen,MessageQueen中又有很多Message,当我们的Handler发送消息的时候,会获取当前的Looper,并在当前的Looper的MessageQueen当中存放我们发送的消息,而我们的MessageQueen也会在Looper的带动下,一直循环的读取Message信息,并将Message信息发送给Handler,并执行HandlerMessage()方法
MessageQueue
Message Queue(消息队列):
定义:采用单链表的数据结构来存储消息列表
作用:存放通过Handler发过来的Message,按照先进先出执行
- 怎么在代码中用Handler
下面我们可以通过代码来看一下Handler
package com.example.dfcn.sexmouth;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class DownlondActivity extends AppCompatActivity {
private TextView downlond_tv;
private Button downlond_btn;
//创建Handler对象
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String data= (String) msg.obj;//接受数据
downlond_tv.setText(data);//接受消息完成操作
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_downlond);
downlond_btn=findViewById(R.id.downlond_btn);
downlond_tv=findViewById(R.id.downlond_tv);
downlond_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(1);//发送消息
Message msg = new Message();
msg.obj = "网络数据";//可以是基本类型,可以是对象,可以是List、map等;
handler.sendMessage(msg);//发送
}
}).start();
}
});
}
}
- 案列解析-简单的倒计时操作
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.dfcn.sexmouth.TimeActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
>
<TextView
android:gravity="center_vertical"
android:text="请输入:"
android:layout_width="50dp"
android:layout_height="50dp" />
<EditText
android:id="@+id/settime_et"
android:gravity="center_vertical"
android:layout_width="30dp"
android:layout_height="50dp" />
<TextView
android:gravity="center_vertical"
android:text="秒"
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:gravity="center"
android:text="倒计时:"
android:layout_width="60dp"
android:layout_height="50dp" />
<TextView
android:id="@+id/time_tv"
android:text="准备"
android:layout_width="match_parent"
android:layout_height="50dp" />
</LinearLayout>
<Button
android:id="@+id/time_btn"
android:text="开始计时"
android:layout_width="match_parent"
android:layout_height="50dp" />
</LinearLayout>
package com.example.dfcn.sexmouth;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class TimeActivity extends AppCompatActivity {
private EditText time_et;
private TextView time_tv;
private Button time_btn;
private int time;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//判断what码
switch (msg.what){
case 1:
time_tv.setText(time+"");
break;
case 2:
time_tv.setText("计时完毕");
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time);
bindID();
time_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new Thread(new Runnable() {
@Override
public void run() {
String s=time_et.getText().toString();//得到输入的秒数
//将string类型的s转换为int
time=Integer.parseInt(s);
while (time>0){
try {
Thread.sleep(1000);//每隔一秒time-1
time--;
} catch (InterruptedException e) {
e.printStackTrace();
}
//当time为0的时候我们传送“what”码2
if (time==0){
handler.sendEmptyMessage(2);
}
//当time不为0时我们传送“what”码1
else if (time!=0){
handler.sendEmptyMessage(1);
}
}
}
}).start();
}
});
}
//初始化控件
private void bindID() {
time_btn=findViewById(R.id.time_btn);
time_et=findViewById(R.id.settime_et);
time_tv=findViewById(R.id.time_tv);
}
}
效果图: