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);
}
}
效果圖: