在主線程中直接寫耗時操作的話很容易引起ANR異常,是以我們都把耗時操作寫在子線程中去完成,但執行完之後,想要更新頁面,又不允許在子線程中去更改頁面 -- 異步任務 或加載器解決了此問題。除了以上兩種解決方式外,使用Thread +Handler也可實作上述效果。
“Handler的作用:注意是在android.os包下的類
(1)、發送并處理消息
(2)、可以排隊執行一系列的動作
此類介紹Handler的最最最基本使用
一. 發送空消息
static final int LOADING_START= ;
static final int LOADING_FINISH=;
Button textView;
/*
* 建立Handler對象,
* */
Handler handler = new Handler(){
//此處接收所有有目前handler對象通過send方法發出的消息
//參數代表接收到的消息對象
@Override
public void handleMessage(Message msg) {
//通過msg對象的what屬性取出目前接收到的消息的辨別
if (msg.what == LOADING_FINISH) {
textView.setText("我要當大牛");
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (Button) findViewById(R.id.textview);
}
//模拟按鈕 進行耗時操作
public void click(View v) {
new Thread(){
@Override
public void run() {
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
//更新頁面操作
/*
* 如果直接在子線程執行更改UI的操作的話
* 會抛出CalledFromWrongThreadException
* 引起程式的崩潰
* 原因:規定子線程不允許操作UI頁面
*
* 注意:Toast,對話框這種彈出視窗的show方法也算是UI操作
* */
// textView.setText("zss");
// Toast.makeText(MainActivity.this,"哈哈先生",Toast.LENGTH_SHORT);
/*
* 不讓在子線程中寫,那麼我就想辦法把我要幹的事情傳出去,在某一個位置
* 接收到我在子線程中傳出的事情,并執行 通過Handler發送消息
* */
//發送一個空消息
handler.sendEmptyMessage(LOADING_FINISH);
}
}.start();
}
完整代碼已貼出,附有詳細注釋,上述代碼隻是發送了一個簡單的空消息。
補充知識點:對于上述發送的消息,結構為 耗時+發送的結構。現在我們改為 發送 + 耗時 +發送 代碼如下:
隻需在如下方法中添加這幾行代碼即可
public void handleMessage(Message msg) {
//通過msg對象的what屬性取出目前接收到的消息的辨別
if (msg.what == LOADING_FINISH) {
textView.setText("我要當大牛");
}else if(msg.what == LOADING_START){
textView.setText("等待時間");
}
super.handleMessage(msg);
}
new Thread(){
@Override
public void run() {
handler.sendEmptyMessage(LOADING_START);
try {
Thread.sl
剩餘代碼都是一樣的,就不完整貼出了。
二. 發送非空消息
** //通過Handler發送非空消息
/*
* 當想要發送非空消息的時候,
* 1.封裝要發送的消息對象
* 在初始化Message對象的時候,推薦使用以下的初始化方式
* 原因:下面的方式比new 的方式效率高,節省記憶體“
* /*
//模拟按鈕 進行耗時操作
public void click(View v) {
new Thread(){
@Override
public void run() {
//handler.sendEmptyMessage(LOADING_START);
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Message msg = Message.obtain(); //第一種方式
Message msg = handler.obtainMessage(); //第二種方式
//向msg中存取資料
msg.what = LOADING_FINISH;
msg.arg1 = ;
msg.arg2 = ;
msg.obj = System.currentTimeMillis();
//調用sendMessage()方法 把Message的對象傳進去
handler.sendMessage(msg);
}
}.start();
}
Handler handler = new Handler(){
//此處接收所有有目前handler對象通過send方法發出的消息
//參數代表接收到的消息對象
@Override
public void handleMessage(Message msg) {
//通過msg對象的what屬性取出目前接收到的消息的辨別
int a =msg.arg1; //取值
int b =msg.arg2; //取值
Long s = (Long) msg.obj;
textView.setText(a+" " + b+" " +s);
super.handleMessage(msg);
}
};
如果想要存儲多個資料的話:采用Bundle 如下:
//模拟按鈕 進行耗時操作
public void click(View v) {
new Thread(){
@Override
public void run() {
//handler.sendEmptyMessage(LOADING_START);
try {
Thread.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Message msg = Message.obtain(); //第一種方式
Message msg = handler.obtainMessage(); //第二種方式
//向msg中存取資料
msg.what = LOADING_FINISH;
Bundle bundle = new Bundle();
bundle.putString("data", "dfasdfa");
bundle.putBoolean("boo", true);
msg.setData(bundle);
//調用sendMessage()方法 把Message的對象傳進去
handler.sendMessage(msg);
}
}.start();
}
Handler handler = new Handler(){
//此處接收所有有目前handler對象通過send方法發出的消息
//參數代表接收到的消息對象
@Override
public void handleMessage(Message msg) {
//通過msg對象的what屬性取出目前接收到的消息的辨別
if(msg.what == LOADING_FINISH) {
Bundle data = msg.getData();
textView.setText(data.getString("data")+" "+data.getBoolean("boo"));
super.handleMessage(msg);
}
}
};
好了,第一節的簡單的handler的用法,先寫到這哈。以上代碼如有不妥指出,還望指出謝謝。。