一般情況下,我們在編寫android代碼的時候,我們會將一些耗時的操作,比如網絡訪問、磁盤訪問放到一個子線程中來執行。而這類操作往往伴隨着UI的更新操作。比如說,訪問網絡加載一張圖片
new Thread() { @Override public void run() { try { URL url = new URL(path); HttpURLConnection connection = (HttpURLConnection) url .openConnection(); // 設置請求方式 connection.setRequestMethod("GET"); // 設置超時時間 connection.setConnectTimeout(10000); int code = connection.getResponseCode(); if (code == 200) { InputStream is = connection.getInputStream(); Bitmap bitmap = BitmapFactory.decodeStream(is); iv_beauty.setImageBitmap(bitmap); } else { Toast.makeText(getApplicationContext(), "圖片獲取失敗!", 0).show(); } } catch (Exception e) { Toast.makeText(getApplicationContext(), "圖片獲取失敗!", 0) .show(); } } }.start();
如果是這樣去操作,就會拋出
10-20 02:50:38.219: W/System.err(497): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
后邊那句英文的大概是說只有創建了UI對象的主線程才能去修改UI
原因在於,在android里面不是線程安全的,所以android有阻止子線程更新組件的機制。
於是我們應該將UI的更新交給主線程來完成,如何去完成,android為我們提供了一套消息處理機制。
它大概的實現步驟是這樣子的
1.子線程利用Handler類發送一條消息,消息會被送完主線程的消息隊列里
2.主線程里邊有一個叫looper的輪詢器,它會循環遍歷消息隊列
3.如果loopler發現消息隊列里有新的消息,android就會調用Handler的handleMessage()方法來處理消息