美文网首页程序员
Android的Activity启动与子线程更新UI

Android的Activity启动与子线程更新UI

作者: Penner | 来源:发表于2016-02-14 17:36 被阅读751次

    最近会将以前阅读过的一些源码做些沉淀与总结
    我们知道现在大多数的GUI框架都是采用单线程模型来处理消息队列和UI更新的,Android自然也是如此。

    启动

    在APK首次启动的时候,Zygote进程会fork个子进程,并在子进程中调用ActivityThread的main函数,主线程的消息队列和ActivityThread实例的初始化都是在此完成的。

    与AMS的通信

    ActivtyManagerService控制着Activity的启动与生命周期,并通过ApplicationThread与ActivityThread进行IPC通信。

    onCreate

    AMS通过ApplicationThread的scheduleLaunchActivity启动一个新的Activity,并通过Handler调用ActivityThread的handleLaunchActivity方法。

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent)  {    
        ......
        Activity a = performLaunchActivity(r, customIntent);
        if  (a != null)  {   
            r.createdConfig = new Configuration(mConfiguration);    
            Bundle oldState = r.state;    
            handleResumeActivity(r.token, false, r.isForward,            
            !r.activity.mFinished && !r.startsNotResumed);
        ......
    }
    
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent)  {
        ......
        if  (r.isPersistable())  {    
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } 
        else  {    
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
        ......
    }
    
    
    Instrumentation.java
    public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState)  {    
        prePerformCreate(activity);    
        activity.performCreate(icicle, persistentState);    
        postPerformCreate(activity);
    }
    
    
    Activity.java
    final void performCreate(Bundle icicle, PersistableBundle persistentState)  {   
       onCreate(icicle, persistentState);    
       mActivityTransitionState.readState(icicle);    
       performCreateCommon();
    }
    

    onResume

    ActivtyThread通过performLaunchActivity的调用做些Activity的初始化,包括创建实例和最终调用Activity的onCreate方法。之后通过调用handleResumeActivity方法

    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume)  {
        ......
        // TODO Push resumeArgs into the activity for consideration
        ActivityClientRecord r =  performResumeActivity(token, clearHide);
        ......
        if (r.window == null && !a.mFinished && willBeVisible)  {   
            if (a.mVisibleFromClient)  {   
                a.mWindowAdded = true;    
                wm.addView(decor, l);
            }
        }
        .....
    
    public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide)  {
        ......
        r.activity.performResume();
        ......
    }
    

    ActivtyThread通过handleResumeActivity调用Activity的onResume方法之后,并在当前Activity的Window为null等情况下,调用WindowMangerGlobal的addView方法将Activity的decorView添加在Window中。

    WindowMangerGlobal.java
    public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow)  {
        ......
        root = new ViewRootImpl(view.getContext(), display);
        view.setLayoutParams(wparams);
        try  {    
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
        ......
    }
    

    重点来了,在Activity的onCreate和onResume调用之后,ActivityThread才创建了ViewRootImpl,并调用setView方法

    ViewRootImpl.java  
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView)  {
        ......
        requestLayout();
        ......
        view.assignParent(this);
      ......
    }
    
    @Override
    public void requestLayout()  {    
        if  (!mHandlingLayoutInLayoutRequest)  {        
            checkThread();       
            mLayoutRequested = true;        
            scheduleTraversals();    
        }
    }
    void invalidate()  {
        mDirty.set(0, 0, mWidth, mHeight);
        if  (!mWillDrawSoon)  {    
            scheduleTraversals();
        }
    }
    

    在此才会检查当前线程是否为主线程,并设置了view的parent,之后一些系统view组件或自定义view会通过调用requestlayout或者invalidate实现view的重新渲染(scheduleTraversals通过Handelr实现)。

    结论

    通过上诉Activity的启动过程可知,我们在Activity的onCreate和onResume中,通过子线程的确可以实现更新某些系统view组件。

    @Override
    protected void onResume()  {    
        super.onResume();    
        new NoUIThread().start();
    }
    class NoUIThread extends Thread  {
        @Override
        public void run()  {
            mNoUITextView.setText("Penner");
        }
    }
    

    相关文章

      网友评论

        本文标题:Android的Activity启动与子线程更新UI

        本文链接:https://www.haomeiwen.com/subject/xuxpkttx.html