(本文由言念小文原創,轉載請注明出處)
一 前言
有Android開發經驗的同學都清楚,UI的更新必須在主線程中進行,且主線程不能被阻塞,否則系統ANR異常。我們往往做一些數據處理是耗時操作,必須要在子線程中進行,然后再將處理后的數據切換到主線程去更新UI,這便是線程切換。
線程切換的本質是“數據的切換”,即將數據從一個線程傳遞到另一個線程。
二 案例描述
老風格,先給出場景案例,然后通過線程切換實現該案例。
案例:在線程A中調用api發送一段數據data,data最終通過線程切換由線程B執行數據處理動作。
三 線程切換基本原理
所謂線程切換,本質就是“數據在線程間切換”,即將一個線程A中的數據,傳遞到另一個線程B執行數據處理操作。基於以上認知,比較自然的實現邏就是:將線程A中的數據進行拷貝,線程B獲取到拷貝數據,然后進行處理,如下圖所示。
四 案例實現代碼
首先創建一個DataHandler類,該類中定義了數據拷貝方法和數據處理線程。在DataHandler中定義了一個用於數據副本存放的成員變量mData;外部模塊可通過sendData()將數據拷貝到DataHandler中;在DataHandler構造中初始化數據處理線程(線程B);該線程重寫的run()方法中用一個while循環不停查詢數據副本mData的值,當檢測到mData有數據時,則執行數據處理動作,數據處理完成后,將數副本mData清空。這樣便實現了將其他外部線程中的數據切換到線程B中處理。
public class DataHandler { // 數據副本 private String mData; public DataHandler() { initSwithThread(); } /** * 發送數據,供外部調用 * @param data */ public void sendData(String data) { // 拷貝數據 mData = data; } private void initSwithThread() { new Thread(new Runnable() { @Override public void run() { while(true) { if(null != mData && mData.length() > 0) { System.out.println("process data, run in thread : " + Thread.currentThread().getName() + ", data = " + mData); // 數據發送后,清除數據副本mData mData = null; } // 為了能夠清晰看清結果這里讓thread休眠1s try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "ThreadB").start(); } }
測試類ThreadTest中創建線程A,然后在A中調用DataHandler實例的數據拷貝方法sendData()將數據切換到線程B中處理。
public class ThreadTest { public static DataHandler mHandler; public static void main(String[] args) { mHandler = new DataHandler(); Thread threadA = new Thread(new Runnable() { @Override public void run() { // 線程A中發送數據 String data = "hello code 9527"; System.out.println("send data, run in thread : " + Thread.currentThread().getName() + ", data = " + data); // 通過DataHandler將數據拷貝到線程B中處理 mHandler.sendData(data); } }, "threadA"); threadA.start(); } }
運行結果:
send data, run in thread : threadA, data = hello code 9527
process data, run in thread : ThreadB, data = hello code 9527
從結果可以看出數據“hello code 9527”在線程A中被DataHandler拷貝出來,副本存放到DataHandler中,然后通過線程B中進行處理。這樣就實現了數據在線程間的切換。實現切換的“靈魂操作”便是“數據拷貝”和“目標線程對拷貝副本的輪詢”。實現原理是不是很簡單?其實Android的Handler機制也是基於這種原理實現的,有興趣的同學可以深入分析一下Handler源碼。