深入理解android UI Thread

本文详细解析了Android中UI线程的工作原理,包括UI线程的初始化过程、视图绘制如何在UI线程中执行以及Activity生命周期如何在UI线程中进行调度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

理解android UI Thread

什么叫做UI Thread

我通常的理解是
1. 执行ui绘制的地方,measure layout draw,
2. android组件activity,service,broadcastreceiver的生命周期都是在ui thread中执行的。如果在ui thread中执行耗时过长的任务,会导致anr

但是为什么会这样,并没有深入理解

UI Thread初始化

我们知道android 进程的初始化后会执行ActivityThread.main(String[] args)方法,不了解的可以看下这里android应用程序初始化流程
看下代码:

 public static void main(String[] args) {

         .
         .
         .
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        .
        .
        .
    }

最关键的代码部分Looper.prepareMainLooper()
这里是初始化主线程的Looper。
看到这可以想到,其实UI Thread其实和HanderThread没什么区别。都是在线程中不断Looper.loop(),然后执行handler.handleMessage(Message)

view的绘制是怎么抛到UI Thread中执行的

我们知道view的绘制会从ViewRootImpl.performTraversals()开始,而这个方法是怎么执行起来的呢?

Created with Raphaël 2.1.0 开始 requestLayout() scheduleTraversals() mChoreographer.postCallback( mTraversalRunnable.run() doTraversal() performTraversal() performMeasure() performLayout() performDraw() 结束

简单解释下:
1. performTraversal()是在mTraversalRunnable中执行的
2. mTraversalRunnable是通过mChoreographer.postCallback调用
3. Choreographer是一个ui绘制的管理类,通过其类成员mFrameHandler来执行的
4. mFrameHandler的初始化参数是Looper.myLooper(), 当这行代码在uiThread中执行的时候looper.myLooper==looper.mainLooper,而实际上这行代码就是在uiThread中执行的

Activity的生命周期是怎么在UI Thread中执行的

源码的角度

Created with Raphaël 2.1.0 activity lifecycle in sourcecode ApplicationThread ApplicationThread ActivityThread ActivityThread Instrumentation Instrumentation Activity Activity scheduleLaunchActivity() handleLaunchActivity : begin newActivity() callActivityOnCreate() handleLaunchActivity : end performCreate() :begin onCreate performCreate() :end

csdn做的图也是醉了,还是我不会用?(编辑模式下完全是正常的)

看下ApplictionThread.scheduleLaunchActivity()代码

 @Override
        public final void scheduleLaunchActivity(Intent intent, ...) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

           .
           .
           .
           sendMessage(H.LAUNCH_ACTIVITY, r);
        }

调用到ActivityThread.sendMessage() 看代码:

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

会用到mH,mH是在Activity.main()中初始化的。也就是说handler是主线程的handler。

侧面验证

activity.runOnUiThread()

public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

可以看到判断是不是ui thread的关键代码
Thread.currentThread() != mUiThread
而 mUiThread thread的赋值是在Activity.onAttach()方法里

 final void attach(Context context, ActivityThread aThread, ...) {    
    .
    .
    .
    mUiThread = Thread.currentThread();
 }

(attach的执行时机是在ActivityThread.performLaunchActivity里在activity类初始化之后,activity生命周期onCreate之前执行)

总结:
1.activity的生命周期是在主线程的任务队列(messageQueue)中等待执行的
2.activity中的mUiThread是ui线程的引用

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值