Android線程中的Looper

一、遇到的問題——調用了Looper.loop()會發(fā)生什么

最近在使用Thread的時候遇到了這樣一個問題,在子線程Thread中顯示一條Toast,在run()方法中增加了Looper.prepare()以及 Looper.loop(),發(fā)現改線程無法被銷毀。
具體如下:

        final Thread testThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(MainActivity.this,"測試toast",Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        });
        testThread.start();

        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.i("xx","線程狀態(tài):"+testThread.getState());
            }
        },10000);

輸出日志如下:

09-01 18:43:45.991 17336-17336/net.loosash.learnthread I/xx: 線程啟動
09-01 18:43:55.998 17336-17336/net.loosash.learnthread I/xx: 線程狀態(tài):RUNNABLE

這也就證明了該Thread會一直執(zhí)行,不會被銷毀,可能會發(fā)生內存泄漏。那么,該如何處理這個問題呢?

二、解決線程銷毀問題

這種情況需要主動處理線程的銷毀,在不需要的時候關閉線程。
關閉線程的方法已經有很多人總結了。網上一搜一大把
https://blog.csdn.net/zhangtengyuan23/article/details/50535813/

三、引發(fā)相關的思考——HandlerThread

遇到這個問題,我第一個想法是HandlerThread,因為這個在android SDK中提供的類內部也維護了一個Looper,并且提供了quit()方法,在使用HandlerThread的時候也要在不需要的時候進行quit()的調用。
這里是HandlerThread的使用方法
https://blog.csdn.net/double2hao/article/details/58598171

四、引發(fā)相關的思考——ActivityThread主線程的消息機制

雖然ActivityThread并不是繼承與Thread,但是作為主線程,內部也維護了一個Looper,以便主線程一直在不停的循環(huán)執(zhí)行,不至于主線程結束掉,導致進程結束。所以我認為最開始的問題,調用了Looper.loop()后,線程進入了死循環(huán),無法自動跳出,導致線程一直存在,無法被銷毀。

五、關于Looper的一些常識

  • 1、線程里一定會有Looper的實例么?
    答案是否定的,Thread是基于java的(package java.lang包中),而Looper是基于android系統(tǒng)的(package android.os包中),所以二者并沒有必然聯系;
  • 2、Looper的作用是什么?
    簡單的說,Looper的作用是處理進程間的消息的,以便實現進程間通訊,是Handler機制的一部分,用來輪訓MessageQueue中的Message,實現接收Message。Handler機制的實現是利用消息隊列的方式,為用戶封裝了一層API,用戶不需要考慮互斥枷鎖的問題,方便用戶的使用。
  • 3、Looper的使用方法
    就是像上面的例子一樣,顯示Toast,子線程間通訊,這里簡單列舉幾條
        // 顯示toast
       Thread testThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(MainActivity.this,"測試toast",Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        });
        // 在子線程中接收使用Handler發(fā)來的消息
        Thread testThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                mHandler = new Handler(Looper.myLooper()){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        //do Something
                    }
                };
                Looper.loop();
            }
        });

六、Looper.loop()到底做了什么——源碼分析

晚點補充吧

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容