前言:通常,我們寫的公共的模塊給別人用,但是這個模塊又必須在特定的線程中執行。
比如,一個加載網絡圖片的的方法,需要在子線程中執行。
/** * 加載網絡圖片 */ private void loadImage() { try { //用延時3秒操作來模擬網絡操作 Thread.sleep( 3000 ); } catch (InterruptedException e) { e.printStackTrace(); } }
但是其他的同事在使用的時候,可能一不小心就在主線程中執行了 loadImage() 方法。這樣就勢必造成了界面卡頓。
為了避免這種情況,我們需要一個線程判斷的工具 ThreadUtil 來幫助我們處理。
- 當前線程是主線程,拋出異常,不去加載
- 當前線程是子線程,繼續執行,完成加載
package com.app; import android.os.Looper; /** * Created by ${zyj} on 2016/6/7. */ public class ThreadUtil { /** * Throws an {@link java.lang.IllegalArgumentException} if called on a thread other than the main thread. */ public static void assertMainThread() { if (!isOnMainThread()) { throw new IllegalArgumentException("You must call this method on the main thread"); } } /** * Throws an {@link java.lang.IllegalArgumentException} if called on the main thread. */ public static void assertBackgroundThread() { if (!isOnBackgroundThread()) { throw new IllegalArgumentException("YOu must call this method on a background thread"); } } /** * Returns {@code true} if called on the main thread, {@code false} otherwise. */ public static boolean isOnMainThread() { return Looper.myLooper() == Looper.getMainLooper(); } /** * Returns {@code true} if called on the main thread, {@code false} otherwise. */ public static boolean isOnBackgroundThread() { return !isOnMainThread(); } }
然后我們把 loadImage() 修改一下,就成了
/** * 加載網絡圖片 */ private void loadImage() { //判斷是否在子線程。 子線程:繼續執行 主線程:拋出異常 ThreadUtil.assertBackgroundThread(); try { //用延時3秒操作來模擬網絡操作 Thread.sleep( 3000 ); } catch (InterruptedException e) { e.printStackTrace(); } }
可以看到在 loadImage() 方法中多了一句: ThreadUtil.assertBackgroundThread();
在 assertBackgroundThread() 方法里,判斷如果不是子線程就直接拋出 "YOu must call this method on a background thread"
正確的調用應該是:在子線程中調用 loadImage() ,比如:
new Thread(new Runnable() { @Override public void run() { loadImage(); } }).start();
總結:
- ThreadUitl 是參考圖片加載框架Glide寫的 .
- ThreadUtil.assertBackgroundThread(); 要求在子線程中執行
- ThreadUtil.assertMainThread() ; 要求在主線程運行
- 代碼示例已上傳到 github: https://github.com/zyj1609wz/ZUtils