編輯:關於Android編程
android中handler的基本使用方法以及運行原理。
最近看mars的android重置版第二季的視頻關於handler的講解,讓我對於這個以前知道怎麼用,卻不是很明白原理的組件的理解瞬間加深了無數倍。mars真的講的很好,視頻真的都蠻不錯的。下面我寫寫自己學習到的知識,以及自己的了解。
handler的基本運行原理 handler怎樣從worker thread傳輸數據到main thread handler怎樣從main thread傳輸數據到worker thread handler的post()方法為什麼我們需要一個handler?我想這是一個最重要的問題,也就是說handler的作用到底是什麼?handler主要是用於線程間的通信,那麼問題又來了,為什麼一個app中需要多個線程,而不是只有一個UI主線程就可以了呢?
假如app中只有一個UI主線程,那麼,當需要進行網絡連接,網絡下載這些等待耗時較長的任務時,android系統就會檢測到UI主線程長時間沒有響應,就會發出一個 application not response的異常警告,簡稱ANR問題。所以,在UI主線程中,是要與用戶實時交互的,不能出現長時間的等待問題。於是,這些任務必須在worker thread中進行。
然而根據android的設定,UI主線程之外的線程,(除了特別的控件,例如progressbar)不能修改UI裡的控件的,這樣又出現了新的問題,我們在子線程獲得的數據,該如何反應的UI上與用戶進行交互?這樣,就出現了這個巧妙的組件,handler!
那麼,handler到底是如何運行的呢?handler對象首先取出一個消息對象,存入到一個消息隊列messagequeue中,然後在另外一端,有一個looper對象,循環的從消息隊列中取出消息對象再交給handler去處理。
public class MainActivity extends ActionBarActivity {
private Handler handler;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.cancleButton);
// 點擊button啟動新線程
button.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Thread thread = new Mythread();
thread.start();
}
});
handler = new Myhandler();
}
// 復寫hanlder中的handlerMessage方法,處理從消息隊列中得到的消息
class Myhandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String s = msg.obj.toString();
System.out.println("在當前線程中"+Thread.currentThread().getName()+"獲得來自這個線程的消息"+s);
}
}
// 在worker thread中使用handler.obtainMessage()方法得到一個Message對象,再把消息存入message中,發入消息隊列
class Mythread extends Thread{
@Override
public void run() {
Message msg = handler.obtainMessage();
msg.obj = currentThread().getName();
handler.sendMessage(msg);
}
}
}
通過這個例子,我們可以看到,handlerMessage()方法是運行在主線程中的,而他可以得到來自worker thread的消息,這樣,就可以將消息在UI界面更新了。
為什麼只是初始化了一個handler對象,就會自動調用他的handleMessage方法?是因為在android.os.Handler類中有一個looper對象,會循環的從消息隊列中取出消息,調用handleM而是撒個方法。
public class MainActivity extends ActionBarActivity {
private Handler handler;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.cancleButton);
// 每點擊一次button,給worker thread 發送一個消息
button.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// 在main中使用handler.obtainMessage()方法得到一個Message對象,再把消息存入message中,發入消息隊列
Message msg = handler.obtainMessage();
msg.obj = Thread.currentThread().getName();
handler.sendMessage(msg);
}
});
Thread thread = new Mythread();
thread.start();
}
// 復寫hanlder中的handlerMessage方法,處理得到的消息
class Myhandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String s = msg.obj.toString();
System.out.println("在當前線程中"+Thread.currentThread().getName()+"獲得來自這個線程的消息"+s);
}
}
// work thread 接受這個消息,並調用handleMeesage()方法處理消息
class Mythread extends Thread{
@Override
public void run() {
// looper對象的loop方法從消息隊列中取出消息,調用handleMeesage()方法處理消息
Looper.prepare();
handler = new Myhandler();
Looper.loop();
}
}
}
通過運行結果可以知道,handleMessage()方法運行在worker thread中,這樣就可以在worker thread中處理來自主線程的消息,實現了進程間的通信。
post方法通過生成一個message,然後把Runnable對象放在message中,再把message放在消息隊列中,然後在主線程中取出這個Runnable對象,在主線程中執行。
public class MainActivity extends ActionBarActivity {
private Handler handler;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.cancleButton);
// 初始化handler,處理得到的Runnable對象
handler = new Handler();
// 點擊按鈕執行worker thread
button.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Thread thread = new Mythread();
thread.start();
}
});
}
class Mythread extends Thread{
@Override
public void run() {
// 在worker thread 中初始化一個Runnable對象
Runnable runnable = new Runnable() {
public void run() {
// 打印出該Runnable方法執行的線程
System.out.println("當前線程名"+Thread.currentThread().getName());
}
};
// post該Runnable對象
handler.post(runnable);
}
}
}
最後的結果,是這個Runnable對象執行在main線程中。有了post()方法,我們可以直接在worker thread中先生成一個Runnable對象,然後在其中寫上更新UI的代碼,直接用post方法即可更新UI。
Android 百度地圖 SDK v3.0.0 (二) 定位與結合方向傳感器
在上一篇博客中,我們成功把地圖導入了我們的項目。本篇我們准備為地圖添加:第一,定位功能;第二,與方向傳感器結合,通過旋轉手機進行道路的方向確認。有了這兩個功能,地圖已經可
Android基礎之——MacOSX下elipse開發環境的配置
前不久換了台macbook,然後自己就把開發環境給配好了,本來這事就這麼過去了,今天有位博友留言讓我寫一篇關於配置的文章,考慮到這個東西確實以後可能還會用,那就寫下來,分
Android中的Low Memory Killer
在現有的技術條件下,內存永遠都是一個吃緊的資源,不用說是PC上會出現內存不足的可能,更不必說在移動設備上了。一旦出現內存不足就會導致系統卡頓,影響用戶體驗。而
自己寫的Android圖表庫XCL-Charts例子展示
話說有了靈感就要抓住,來了興趣就要去研究它。 所以雖然最近很忙,但我還是沒有丟下Android圖表實現的研究,終於現在我的圖表庫基類 基本上已經有點模樣了,不在是小打小鬧