編輯:關於Android編程
1、安卓為什麼只能通過消息機制更新UI呢?
最根本的目的就是解決多線程並發問題。(多個線程同時執行一個任務)
假如在一個Activity中,有多個線程去更新UI,並且都沒有加鎖機制,那就會造成更新UI錯亂。如果對更新UI的操作都進行加鎖處理,就會造成性能下降。使用消息機制,根本不用關系多線程的問題,因為更新UI的操作,都是在主線程的消息隊列當中去輪詢處理的。
2、Handler是什麼?
Handler是android提供的一套更新UI的機制,也是消息處理機制,我們可以用它發送消息,也可以通過它處理消息。
更新UI,傳遞消息,處理消息。
3、默認情況下Handler會與其被定義時所在線程的Looper綁定,比如,Handler在主線程中定義,那麼它是與主線程的Looper綁定。
注意Handler的構造函數,New Handler()什麼參數都不需要
/** * Created on 2016/9/23. * Author:crs * Description:測試消息機制:主要用於線程間通訊,注意Handler類的構造函數 * 1)一個完整的消息要包括消息標識和消息內容.(消息對象裡面包含消息消息標識和消息內容;如果是空消息,只有消息標識沒有消息體) * * 2)只有在原生線程(主線程)才能更新UI,在子線程更新UI會報錯。 * * 3)使用消息機制更新UI的模板性代碼:創建Handler實例,在子線程中調用post方法,就兩步操作。 * handler.post(r): r是要執行的任務代碼,意思就是說r的代碼實際是在UI線程執行的,可以寫更新UI的代碼。 * * 4)使用消息機制更新UI的模板性代碼:創建Handler實例,重寫handleMessage()方法,創建消息對象並進行信息傳遞即可。 * obtainMessage() Message類 arg1 arg2 sendMessage(message實例) sendToTarget(); sendEmptyMessage() * * 5)使用消息機制實現圖片輪播:創建Handler實例,創建Runnable接口實例,調用postDelayed(runnable實例,毫秒值); * removeCallbacks(Runnable),就這幾步常規的操作 * * 6)創建Handler的時候,指定callBack;可以通過CallBack截獲Handler傳遞的消息. */
案例一:安卓中更新UI的四種方式
package com.crs.demo.ui.handler;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;
/**
* Created on 2016/10/9.
* Author:crs
* Description:安卓中四種更新UI的方式
* 1)handler.post()
* 2)handler.sendMessage()
* 3)runOnUIThread()
* 4)View.post
*/
public class TestUpdateUIActivity extends BaseActivity {
private static final int SUCCESS_GET_DATA = 1;
private Handler mHandler = new Handler();
private Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SUCCESS_GET_DATA: {
tv_activity_test_update_ui.setText("使用handler.sendMessage()更新");
}
break;
}
}
};
private TextView tv_activity_test_update_ui;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_update_ui);
initViews();
}
private void initViews() {
tv_activity_test_update_ui = findView(R.id.tv_activity_test_update_ui);
Button btn_test_handler1 = findView(R.id.btn_test_handler1);
Button btn_test_handler2 = findView(R.id.btn_test_handler2);
Button btn_test_handler3 = findView(R.id.btn_test_handler3);
Button btn_test_handler4 = findView(R.id.btn_test_handler4);
//第一種方式:在子線程中調用runOnUIThread()更細UI
btn_test_handler1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_activity_test_update_ui.setText("調用runOnUIThread方法更新");
}
});
}
}).start();
}
});
//第二種方式:使用View的post()更新UI
btn_test_handler2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv_activity_test_update_ui.post(new Runnable() {
@Override
public void run() {
tv_activity_test_update_ui.setText("使用View的post()更新UI");
}
});
}
});
//第三種方式:使用Handler的post()更新UI
btn_test_handler3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
tv_activity_test_update_ui.setText("Handler的post()更新UI");
}
});
}
}).start();
}
});
//第四種方式:使用Handler的sendMessage()更新UI
btn_test_handler4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
//Message message = new Message();
//Message message = myHandler.obtainMessage();
myHandler.sendEmptyMessage(SUCCESS_GET_DATA);
}
}).start();
}
});
}
}
案例二:攔截Handler傳遞的消息
package com.crs.demo.ui.handler;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;
import com.crs.demo.utils.ToastUtils;
/**
* Created on 2016/10/8.
* Author:crs
* Description:測試創建Handler指定CallBack
*/
public class TestCallBackActivity extends BaseActivity {
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
//可以通過CallBack截獲Handler傳遞的消息,返回值表示是否截獲消息,false表示不截獲。
ToastUtils.showShort(TestCallBackActivity.this, "1");
//如果設置為true,就表示截獲消息,後面的handleMessage()就不在繼續執行了,即2不會被打印了。
return false;
}
}) {
@Override
public void handleMessage(Message msg) {
ToastUtils.showShort(TestCallBackActivity.this, "2");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_call_back);
initViews();
}
private void initViews() {
Button btn_activity_test_call_back = findView(R.id.btn_activity_test_call_back);
btn_activity_test_call_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mHandler.sendEmptyMessage(1);
}
});
}
}
案例三:使用Handler實現圖片輪播效果
package com.crs.demo.ui.handler;
import android.os.Bundle;
import android.os.Handler;
import android.widget.ImageView;
import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;
/**
* Created on 2016/10/8.
* Author:crs
* Description:使用消息機制實現圖片輪播效果
* 關鍵是練習消息機制的使用
*/
public class TestPostDelayedActivity extends BaseActivity {
int[] image = {R.drawable.iv_1, R.drawable.iv_2, R.drawable.iv_3};
int index;
private ImageView iv_test_post_delayed;
//1)創建Handler實例
private Handler mHandler = new Handler();
//2)創建Runnable實例
private MyRunnable myRunnable = new MyRunnable();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_post_delayed);
iv_test_post_delayed = findView(R.id.iv_test_post_delayed);
//3)調用此方法實現定時器效果
mHandler.postDelayed(myRunnable, 1000);
}
//實現接口
class MyRunnable implements Runnable {
@Override
public void run() {
index++;
//余數只有三種類型0、1、2
index = index % 3;
//每隔多少秒要做的事(業務邏輯)
iv_test_post_delayed.setImageResource(image[index]);
mHandler.postDelayed(this, 1000);
}
}
@Override
protected void onPause() {
super.onPause();
//清除此定時器效果
mHandler.removeCallbacks(myRunnable);
}
}
案例四:自定義與線程相關的handler
package com.crs.demo.ui.handler;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;
import com.crs.demo.utils.LogUtils;
/**
* Created on 2016/10/9.
* Author:crs
* Description:自定義與線程相關的Handler
*/
public class TestCustomHandlerActivity extends BaseActivity {
private static final String TAG = "TestCustomHandler";
private MyThread myThread;
//創建主線程Handler
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
LogUtils.i(TAG, Thread.currentThread() + "主線程");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_custom_handler);
myThread = new MyThread();
myThread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//主線程中的Handler
mHandler.sendEmptyMessage(1);
//子線程中的Handler
myThread.myHandler.sendEmptyMessage(2);
}
class MyThread extends Thread {
private Handler myHandler;
@Override
public void run() {
super.run();
Looper.prepare();
myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
LogUtils.i(TAG, Thread.currentThread() +"子線程");
}
};
Looper.loop();
}
}
}
Handler的原理是什麼?
1)Handler封裝了消息的發送,主要包括消息發送給誰。
2)Looper:內部包含一個消息隊列,也就是MessageQueue,所有Handler發送的消息都會走向這個消息隊列。
Looper類中有一個loop()方法,它不斷的從MessageQueue中取消息,如果有消息就處理消息,如果沒有消息就阻塞。
3)MessageQueue就是一個消息隊列,可以添加消息、移除消息。
4)Handler內部會和Looper進行關聯,在Handler內部可以找到Looper。使用Handler發送消息,其實就是向MessageQueue隊列中發送消息。
總結:handler負責發送消息,Looper負責接收Handler發送的消息,並直接發消息傳回給handler自己、MessageQueue就是一個存儲消息的容器、looper是循環器。
消息標識與消息內容(int類型和對象類型)
如何獲取一個Message對象?
Handler的兩種作用:發送消息、傳遞消息.
Message與Handler之間的關系 sendToTarget()
Handler移除一個事件,停止事件的執行removeCallBack(runnable實例)
發送一個空消息的目的是什麼原理是什麼
截獲Handler發送的消息 new CallBack()
來一個自定義TextView計時操作
傳統的 登陸界面總有那些 點擊發送驗證碼然後等待接受的一個計時操作,今天就上一個類似的實現(不用傳統方法咯)先看下效果:貌不驚人,我們先來看看傳統的Handl
Android手機輸入法按鍵監聽-dispatchKeyEvent
最近在項目開發中遇到一個關於手機輸入鍵盤的坑,特來記錄下。應用場景:項目中有一個界面是用viewpaper加三個fragment寫的,其中viewpaper被我屏蔽了左右
Android編程實現調用系統分享功能示例
本文實例講述了Android編程實現調用系統分享功能。分享給大家供大家參考,具體如下:/** * 調用系統的分享功能 * Created by admin on 15-4
Android Multimedia框架總結(十三)CodeC部分之OpenMAX框架初識及接口與適配層實現
前言:上篇中介紹OMX事件回調,從今天開始,走入Codec部分之OpenMAX框架裡。看下今天的Agenda如下:一張圖回顧音視頻同步 一張圖看清OpenMAX在Andr