回憶一個簡單的Handler使用
class TestActivity : AppCompatActivity() {
private var mUIHandler = Handler{
when(it.what) {
1 -> {
Log.d("ggp", "hello handler")
}
2 -> {
Log.d("ggp", "hello handler")
}
}
false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
}
}
大家都知道泡一,子線程需要更新UI的時候是需要發(fā)送消息給主線程handler,然后處理ui卓囚,那么好奇一下這里的handler是怎么與activity 主線程(UI線程)綁定的瘾杭?
首先好奇一下Activity主線程是啥?
回到ActivityThread中看一下mian是怎么實現(xiàn)的
public static void main(String[] args) {
............
//創(chuàng)建looper
Looper.prepareMainLooper();
...........
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
//拿到handler
sMainThreadHandler = thread.getHandler();
}
...............
//進入looper無線循環(huán)
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
準備主線程 looper prepareMainLooper
public static void prepareMainLooper() {
//準備looper
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//get到looper
sMainLooper = myLooper();
}
}
繼續(xù)
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//與上邊遙相呼應(yīng) 這里set哪亿,將當前l(fā)ooper set給sThreadLocal
sThreadLocal.set(new Looper(quitAllowed));
}
looper構(gòu)造函數(shù)
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
這里new 了一個MessageQueue,設(shè)置thread為當前Thread粥烁,也就activityThread自己。
繼續(xù)回到Activity Handler初始化過程蝇棉。
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//獲取到當前l(fā)ooper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
分析一下讨阻,這里獲取到當前thead的looper,由于我們activity是跑在主進程篡殷,當然獲取到的就是主線程的looper钝吮,繼續(xù)想一下我們向handler發(fā)送消息,就是發(fā)送給了主線程Looper板辽。
當前activity中的UIHandler其實拿到了主線程的Looper然后就可以處理主線程任務(wù)啦奇瘦。
activity可以有多個Handler但是拿到的都是主線程的looper。因為在new Handler的時候就自動綁定了主線程looper劲弦。
順道看一下HandlerThread使用
private var mHandlerThread: HandlerThread? = HandlerThread("ggpthread")
fun test() {
mGgpHandler = Handler(mHandlerThread!!.looper) {
when(it.what){
1 -> {
Log.d("ggp", "hello HandlerThread")
}
}
false
}
}
使用相當簡單耳标,這里需要對比一下HandlerThread,在使用第一要務(wù)就是getlooper(),我這里使用kotlin寫的demo,java也是一樣的邑跪〈纹拢看一下getLooper怎么實現(xiàn)的
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
這里wait,等待mLooper初始化画畅,看一下mLooper初始化:
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
當前Thread run中初始化砸琅,并且開始looper循環(huán)。
總結(jié)一下轴踱,初始化HandlerThread之后我們就會調(diào)用線程start