關(guān)于Android線程與Handler的理解。

概述

我們都知道,更新UI只能在主線程中操作,若是在子線程中訪問(wèn)UI控件,容易引起阻塞。
問(wèn)題來(lái)了,什么是主線程,什么是子線程?

主線程

主線程是指進(jìn)程所擁有的線程。當(dāng)一個(gè)android程序啟動(dòng)時(shí),會(huì)單獨(dú)啟動(dòng)一個(gè)進(jìn)程,默認(rèn)情況下只有一個(gè)。程序啟動(dòng)時(shí),進(jìn)程會(huì)啟動(dòng)一個(gè)主線程,也就是UI線程,主要是負(fù)責(zé)控制UI界面的顯示、更新和控件交互。Android的主線程就是ActivityThread,主線程的入口方法為Main,在main方法中系統(tǒng)會(huì)通過(guò)Looper.prepareMainLooper()來(lái)創(chuàng)建主線程的Looper以及MessageQueue,并通過(guò)Looper.loop()來(lái)開(kāi)啟主線程的消息循環(huán)??匆幌逻^(guò)程。

    public static ActivityThread currentActivityThread() {  
        return sThreadLocal.get();  
    }  
  
   
    public static void main(String[] args) {  
        SamplingProfilerIntegration.start();  
  
        // CloseGuard defaults to true and can be quite spammy.  We  
        // disable it here, but selectively enable it later (via  
        // StrictMode) on debug builds, but using DropBox, not logs.  
        CloseGuard.setEnabled(false);  
  
        Environment.initForCurrentUser();  
  
        // Set the reporter for event logging in libcore  
        EventLogger.setReporter(new EventLoggingReporter());  
  
        Process.setArgV0("<pre-initialized>");  
  
        Looper.prepareMainLooper();  
  
        // 創(chuàng)建ActivityThread實(shí)例  
        ActivityThread thread = new ActivityThread();  
        thread.attach(false);  
  
        if (sMainThreadHandler == null) {  
            sMainThreadHandler = thread.getHandler();  
        }  
  
        AsyncTask.init();  
  
        if (false) {  
            Looper.myLooper().setMessageLogging(new  
                    LogPrinter(Log.DEBUG, "ActivityThread"));  
        }  
  
        Looper.loop();  
  
        throw new RuntimeException("Main thread loop unexpectedly exited");  
    }  
}  

子線程

子線程主要負(fù)責(zé)一些耗時(shí)任務(wù)的執(zhí)行,再配合主線程進(jìn)行UI的更新。
子線程默認(rèn)是沒(méi)有Looper的,若是使用Handler進(jìn)行消息的傳遞,需要手動(dòng)進(jìn)行創(chuàng)建Looper

new Thread(){
@override
public void run(){
Looper.prepare();//創(chuàng)建Looper對(duì)象
Handler handler = new Handler();//這種構(gòu)造方式會(huì)默認(rèn)使用當(dāng)前線程的Looper
Looper.loop();//Looper開(kāi)始工作
  }
}.start();

但這種情況下是不能通過(guò)handler更新UI的,因?yàn)閔andler并沒(méi)有實(shí)例化在主線程中。這時(shí)值能處理非更新UI的的操作。如果你想在這個(gè)子線程中更新UI的話,需要這么做

Handler handler = new Handler(Looper.getMainLooper());

這種構(gòu)造方式引用了主線程的Looper,表示放到主UI線程去處理,所以可以更新UI。

判斷當(dāng)前線程是否為主線程。

  • 方法一:使用Looper類判斷
    Looper.myLooper() == Looper.getMainLooper();

  • 方法二:通過(guò)查看Thread類的當(dāng)前線程
    Thread.currentThread() == Looper.getMainLooper().getThread()

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容