TShopping

 找回密碼
 註冊
搜索
查看: 157|回復: 0

[教學] 多線程--異步處理機制之Handler詳解

[複製鏈接]
發表於 2016-8-5 07:54:05 | 顯示全部樓層 |閱讀模式
 
Push to Facebook Push to Plurk Push to Twitter 
Handler的定義
  主要接受子線程發送的數據,並用此數據配合主線程更新UI.
      解釋 :當應用程序啟動時,Android首先會開啟一個主線程(也就是UI線程) ,主線程為管理界面中的UI控件,進行事件分發。
  比如說,你要是點擊一個Button, Android會分發事件到Button上,來響應你的操作。如果此時需要一個耗時的操作,例如:聯網讀取數據,或者讀取本地較大的一個文件的時候,你不能把這些操作放在主線程中,如果你放在主線程中的話,界面會出現假死現象,如果5秒鐘還沒有完成的話,會收到Android系統的一個錯誤提示"強制關閉".這個時候我們需要把這些耗時的操作,放在一個子線程中,因為子線程涉及到UI更新,Android主線程是線程不安全的,也就是說,更新UI只能在主線程中更新,子線程中操作是危險的 .
  這個時候,Handler就出現了來解決這個複雜的問題,由於Handler運行在主線程中(UI線程中),它與子線程可以通過Message對象來傳遞數據,這個時候,Handler就承擔著接受子線程傳過來的(子線程用sedMessage()方法傳弟)Message對象,(裡麵包含數據) ,把這些消息放入主線程隊列中,配合主線程進行更新UI。

Handler、Looper、Message 和MessageQueue 的關係Handler 向MessageQueue 發送Message,Looper 負責循環MessageQueue 中的Message 並向Handler 分發Message,最後Handler 負責處理Message。示意圖如下
handler.jpg
Handler一些特點
  handler可以分發Message對象和Runnable對像到 ​​主線程中,每個Handler實例,都會綁定到創建他的線程中(一般是位於主線程),
  它有兩個作用:
  • 安排消息或Runnable 在某個主線程中某個地方執行
  • 安排一個動作在不同的線程中執行
  Handler中分發消息的一些方法

  1. post(Runnable)
  2. postAtTime(Runnable,long)
  3. postDelayed(Runnable long)
  4. sendEmptyMessage(int)
  5. sendMessage(Message)
  6. sendMessageAtTime(Message,long)
  7. sendMessageDelayed(Message,long)
複製代碼


  以上post類方法允許你排列一個Runnable對像到 ​​主線程隊列中,
  sendMessage類方法,允許你安排一個帶數據的Message對像到 ​​隊列中,等待更新.

Handler實例
  子類需要繼承Handler類,並重寫handleMessage(Message msg)方法 ,用於接受線程數據
  以下為一個實例,它實現的功能為: 通過線程修改界面Button的內容


  1. public class MyHandlerActivity extends Activity {
  2.     Button button;
  3.     MyHandler myHandler;

  4.     protected void onCreate(Bundle savedInstanceState) {
  5.         super.onCreate(savedInstanceState);
  6.         setContentView(R.layout.handlertest);

  7.         button = (Button) findViewById(R.id.button);
  8.         myHandler = new MyHandler();
  9.         // 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据
  10.         // Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象
  11.         // (2): 让一个动作,在不同的线程中执行.

  12.         // 它安排消息,用以下方法
  13.         // post(Runnable)
  14.         // postAtTime(Runnable,long)
  15.         // postDelayed(Runnable,long)
  16.         // sendEmptyMessage(int)
  17.         // sendMessage(Message);
  18.         // sendMessageAtTime(Message,long)
  19.         // sendMessageDelayed(Message,long)
  20.       
  21.         // 以上方法以 post开头的允许你处理Runnable对象
  22.         //sendMessage()允许你处理Message对象(Message里可以包含数据,)

  23.         MyThread m = new MyThread();
  24.         new Thread(m).start();
  25.     }

  26.     /**
  27.     * 接受消息,处理消息 ,此Handler会与当前主线程一块运行
  28.     * */

  29.     class MyHandler extends Handler {
  30.         public MyHandler() {
  31.         }

  32.         public MyHandler(Looper L) {
  33.             super(L);
  34.         }

  35.         // 子类必须重写此方法,接受数据
  36.         @Override
  37.         public void handleMessage(Message msg) {
  38.             // TODO Auto-generated method stub
  39.             Log.d("MyHandler", "handleMessage......");
  40.             super.handleMessage(msg);
  41.             // 此处可以更新UI
  42.             Bundle b = msg.getData();
  43.             String color = b.getString("color");
  44.             MyHandlerActivity.this.button.append(color);

  45.         }
  46.     }

  47.     class MyThread implements Runnable {
  48.         public void run() {

  49.             try {
  50.                 Thread.sleep(10000);
  51.             } catch (InterruptedException e) {
  52.                 // TODO Auto-generated catch block
  53.                 e.printStackTrace();
  54.             }

  55.             Log.d("thread.......", "mThread........");
  56.             Message msg = new Message();
  57.             Bundle b = new Bundle();// 存放数据
  58.             b.putString("color", "我的");
  59.             msg.setData(b);

  60.             MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI

  61.         }
  62.     }
複製代碼
完善程序邏輯
  • 在關閉Activity 的時候停掉你的後台線程。線程停掉了,就相當於切斷了Handler 和外部連接的線,Activity 自然會在合適的時候被回收。
  • 如果Handler 是被delay 的Message 持有了引用,那麼使用相應的Handler 的removeCallbacks() 方法,把消息對像從消息隊列移除就行了。

 

臉書網友討論
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2016-12-10 17:15 , Processed in 0.059971 second(s), 26 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表