回憶一個(gè)簡(jiǎn)單的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的時(shí)候是需要發(fā)送消息給主線程handler,然后處理ui,那么好奇一下這里的handler是怎么與activity 主線程(UI線程)綁定的?
首先好奇一下Activity主線程是啥?
回到ActivityThread中看一下mian是怎么實(shí)現(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();
}
...............
//進(jìn)入looper無線循環(huán)
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
準(zhǔn)備主線程 looper prepareMainLooper
public static void prepareMainLooper() {
//準(zhǔn)備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,將當(dāng)前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 了一個(gè)MessageQueue,設(shè)置thread為當(dāng)前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());
}
}
//獲取到當(dāng)前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();
}
分析一下,這里獲取到當(dāng)前thead的looper,由于我們activity是跑在主進(jìn)程,當(dāng)然獲取到的就是主線程的looper,繼續(xù)想一下我們向handler發(fā)送消息,就是發(fā)送給了主線程Looper。
當(dāng)前activity中的UIHandler其實(shí)拿到了主線程的Looper然后就可以處理主線程任務(wù)啦。
activity可以有多個(gè)Handler但是拿到的都是主線程的looper。因?yàn)樵趎ew Handler的時(shí)候就自動(dòng)綁定了主線程looper。
順道看一下HandlerThread使用
private var mHandlerThread: HandlerThread? = HandlerThread("ggpthread")
fun test() {
mGgpHandler = Handler(mHandlerThread!!.looper) {
when(it.what){
1 -> {
Log.d("ggp", "hello HandlerThread")
}
}
false
}
}
使用相當(dāng)簡(jiǎn)單,這里需要對(duì)比一下HandlerThread,在使用第一要?jiǎng)?wù)就是getlooper(),我這里使用kotlin寫的demo,java也是一樣的。看一下getLooper怎么實(shí)現(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;
}
當(dāng)前Thread run中初始化,并且開始looper循環(huán)。
總結(jié)一下,初始化HandlerThread之后我們就會(huì)調(diào)用線程start