編輯:關於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。
在上一篇博客中,我們成功把地圖導入了我們的項目。本篇我們准備為地圖添加:第一,定位功能;第二,與方向傳感器結合,通過旋轉手機進行道路的方向確認。有了這兩個功能,地圖已經可
前不久換了台macbook,然後自己就把開發環境給配好了,本來這事就這麼過去了,今天有位博友留言讓我寫一篇關於配置的文章,考慮到這個東西確實以後可能還會用,那就寫下來,分
在現有的技術條件下,內存永遠都是一個吃緊的資源,不用說是PC上會出現內存不足的可能,更不必說在移動設備上了。一旦出現內存不足就會導致系統卡頓,影響用戶體驗。而
話說有了靈感就要抓住,來了興趣就要去研究它。 所以雖然最近很忙,但我還是沒有丟下Android圖表實現的研究,終於現在我的圖表庫基類 基本上已經有點模樣了,不在是小打小鬧