前言:通常,我們寫的公共的模塊給別人用,但是這個模塊又必須在特定的線程中執行。
比如,一個加載網絡圖片的的方法,需要在子線程中執行。
/**
* 加載網絡圖片
*/
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
