前言:Android開發當中,絕大多數的UI操作都應該在主線程當中進行,主線程之外原則上不允許修改View(progressBar等特殊控件除外)。在一個應用程序當中,主線程通常用於接收用戶的輸入信息,以及將運算的結果反饋給用戶,因此,對一些可能會產生阻塞的操作,必須放置在WorkerThread(子線程)中,但WorkerThread中的參數又不能反饋給主線程,因此就產生了一種通信方法:Handler!
一.1.Handler用來處理主線程與子線程之間的數據傳輸。
作用:把消息放到消息隊列中。
2.Looper:消息隊列循環器,不斷的從消息隊列中取出消息,取出的消息會再交給Handler來處理。如果消息隊列沒有消息,Looper會等待,該線程就會出現阻塞。
Java Code:
package com.gu.aatest;
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.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button mButton;
private TextView mTextView;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.button);
mTextView = (TextView) findViewById(R.id.textview);
handler = new FirstHandler();
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// obtainMessage() 獲取一個消息對象
Message msg = handler.obtainMessage();
// what爲msg的屬性
msg.what = 2;
/**
* 將消息放到消息隊列中
*
* 步驟:1.Looper取出消息;2.Looper將會找到與消息對象對應的Handler對象;3.L
* ooper將會調用Handler的handleMessage()方法來處理信息對象
*/
handler.sendMessage(msg);
}
});
}
class FirstHandler extends Handler {
// 用來處理消息的handleMessage()方法
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
int what = msg.what;
System.out.println("what:" + what);
}
}
}
二.子線程向主線程發送消息
package com.gu.aatest;
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.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button mButton;
private TextView mTextView;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.button);
mTextView = (TextView) findViewById(R.id.textview);
handler = new FirstHandler();
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// obtainMessage() 獲取一個消息對象
Thread t = new NetWorkThread();
t.start();
}
});
}
class FirstHandler extends Handler {
// 用來處理消息的handleMessage()方法
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
System.out.println("FirstHandler--當前線程爲:"
+ Thread.currentThread().getName());
String s = (String) msg.obj;
mTextView.setText(s);
}
}
// 模擬從網絡加載數據
class NetWorkThread extends Thread {
/**
* 重載方法
*/
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(2 * 1000);
System.out.println("NetWorkThread--當前線程爲:"
+ Thread.currentThread().getName());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String s = "從網絡加載數據";
// 此處不能直接用TextView。setText(s)來顯示,否則會報錯
Message msg = handler.obtainMessage();
// sendMessage(msg)方法無論在主線程還是子線程都能發送
handler.sendMessage(msg);
}
}
}
打印結果如下,下面的main爲主線程,其餘爲子線程
三.主線程向子線程發送消息
package com.gu.aatest;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button mButton;
private TextView mTextView;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.button);
mTextView = (TextView) findViewById(R.id.textview);
Thread thread = new NetWorkThread();
thread.start();
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// obtainMessage() 獲取一個消息對象
Message msg = handler.obtainMessage();
handler.sendMessage(msg);
System.out.println("當前線程爲:" + Thread.currentThread().getName());
}
});
}
// 模擬從網絡加載數據
class NetWorkThread extends Thread {
/**
* 重載方法
*/
@Override
public void run() {
// TODO Auto-generated method stub
// 準備Looper
Looper.prepare();
handler = new Handler() {
/**
* 重載方法
*
* @param msg
*/
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
System.out.println("NetWorkThread--當前線程爲:"
+ Thread.currentThread().getName());
System.out.println("收到消息");
}
};
/**
* 調用Looper的Loop()方法後,Looper對象將不斷的從消息隊列中取出消息對象,
* 然後調用handler的handleMessage()方法處理消息對象,如果消息隊列中沒有了消息對象,則會線程阻塞
*/
Looper.loop();
}
}
}
輸出結果如下;