android主線程與Handler

回憶一個(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容