View

//前提怎么调用到performLaunchActivity
就是Activity.startActivity->
Instrumentation.execStartActivity(app 进程的 ActivtyManagerProxy,然后进入 system server 进程,到 ActivityManagerNative,最终到达 ActivityManagerService)->
ActivityManagerService.startActivity( system server 进程)->
ActivityStarter.startActivityMayWait->ActivityStackSupervisor.resolveIntent (去解析 Intent 和 [Activity)->
PackageManagerService.resolveIntent (resolveActivity() 方法的核心功能是找到相应的Activity 组件,并保存到 intent 对象。做的工作就是检查权限,从 Manifest 中读取 Activity 的配置)->
ActivityStarter.startActivityLocked()->
ActivityStack.startActivityLocked->
ActivityManagerService.startProcessLocked()->
ActivityManagerService.attachApplicationLocked
在 Framework篇 - 四大组件与进程启动的关系 这篇文章中,详细介绍了 ActivityManagerService.startProcessLocked() 整个过程,创建完新进程后会在新进程中调用 ActivityManagerProxy.attachApplication() ,该方法经过 Binder IPC 后调用到ActivityManagerService.attachApplicationLocked()。->
ApplicationThreadProxy.scheduleLaunchActivity()->
IPC 到 ActivityManagerNative 的 onTransaction():

@Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        //...
        case SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION:
        {
            scheduleLaunchActivity(intent, b, ident, info, curConfig, overrideConfig, compatInfo,
                    referrer, voiceInteractor, procState, state, persistentState, ri, pi,
                    notResumed, isForward, profilerInfo);
            return true;
        }

-> ActivityThread (内部有 ApplicationThread 内部类)
ActivityThread的ApplicationThread

private class ApplicationThread extends ApplicationThreadNative{
           case LAUNCH_ACTIVITY: {
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
会发送消息到 ActivityThread 的 H 类:
private class H extends Handler {
    //...
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
 
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;              
}

->
ActivityThread.handleLauchActivity():->
ActivityThread.performLaunchActivity()->


image.png

点击桌面 App 图标,Launcher 进程采用 Binder IPC 向 system_server 进程发起 startActivity 请求;
system_server 进程接收到请求后,向 zygote 进程发送创建进程的请求;
Zygote 进程 fork 出新的子进程,即 App 进程;
App 进程,通过 Binder IPC 向 sytem_server 进程发起 attachApplication 请求;
system_server 进程在收到请求后,进行一系列准备工作后,再通过 binder IPC 向 App 进程发送 scheduleLaunchActivity 请求;
App 进程的 Binder 线程 (ApplicationThread) 在收到请求后,通过 handler 向主线程发送 LAUNCH_ACTIVITY 消息;
主线程在收到 Message 后,通过发射机制创建目标 Activity,并回调 Activity.onCreate() 等方法;
到此,App 便正式启动,开始进入 Activity 生命周期,执行完 onCreate/onStart/onResume 方法,UI 渲染结束后便可以看到App 的主界面。

https://www.cnblogs.com/JMatrix/p/8296427.html

public class View绘制流程 {

    /**
     * 前提在 在activity performLaunchActivity的时候就创建了 phonewindow decoreView
     */

    /*** {android/app/ActivityThread.java}**/
    @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason) {
        // TODO Push resumeArgs into the activity for consideration
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        final Activity a = r.activity;
        View decor = r.window.getDecorView();
        decor.setVisibility(View.INVISIBLE);
        ViewManager wm = a.getWindowManager();
        a.mDecor = decor;
        if (r.activity.mVisibleFromClient) {
            //// 添加视图
            r.activity.makeVisible();
        }
    }

    /*** {android/app/Activity.java}***/
    void makeVisible() {
        // 如果Window没有被添加,则addView添加decorView
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            // 进入WindowManagerGlobal.addView,这边是添加DecorView,根view
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        // 设置decorView可见
        mDecor.setVisibility(View.VISIBLE);
    }

    /*** {android/view/WindowManagerGlobal.java}**/
    public void addView(View view, ViewGroup.LayoutParams params,
                        Display display, Window parentWindow, int userId) {
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
        ViewRootImpl root;
        View panelParentView = null;
        // 每次调用global.addView()都会创建一个ViewRootImpl,它是decorView与WMS沟通的桥梁
        root = new ViewRootImpl(view.getContext(), display);
        view.setLayoutParams(wparams);
        mViews.add(view);
        // ViewRootImpl设置View
        root.setView(view, wparams, panelParentView, userId);
    }

    /*** {android/view/ViewRootImpl.java}**/
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
                        int userId) {
        ////View的绘制流程
        requestLayout();
        //创建InputChannel
        InputChannel inputChannel = new InputChannel();
        //通过WindowSession进行IPC调用,将View添加到Window上
        //mWindow即W类,用来接收WmS信息
        //同时通过InputChannel接收触摸事件回调
        res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
                getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
                mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                mAttachInfo.mDisplayCutout, inputChannel,
                mTempInsets, mTempControls);
        //处理触摸事件回调
        mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                Looper.myLooper());
    }

    /*** {android/view/ViewRootImpl.java}**/
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread(); //checkThread():只能在主线程更新 UI。
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }

    /*** {android/view/ViewRootImpl.java}**/
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        }
    }

    /*** {android/view/ViewRootImpl.java}**/
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }

    final TraversalRunnable mTraversalRunnable = new TraversalRunnable();

    /*** {android/view/ViewRootImpl.java}**/
    void doTraversal() {
        performTraversals();
    }

    /*** {android/view/ViewRootImpl.java}**/

    private void performTraversals() {
        int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
        int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
        // 测量
        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
        // 布局
        performLayout(lp, mWidth, mHeight);
        // 绘制
        performDraw();
        // ...
    }

    /*** {android/view/ViewRootImpl.java}**/
    private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
        //根视图开始 measure 了,所以就是 decorView 了。decorView 是个 FrameLayout,
        // 所以我们就来看 FrameLayout 的measure() 方法。FrameLayout 里面没有 measure(),
        // 只有 onMeasure(),measure() 方法在其父类 View 里,measure() 方法中会调用 onMeasure()
        mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }

    /*** {android/view/ViewRootImpl.java}**/
    private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
                               int desiredWindowHeight) {// ...
        final View host = mView;
        //执行到view  layout
        host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
    }

    /*** {android/view/ViewRootImpl.java}**/
    private void performDraw() {
        draw(fullRedrawNeeded);
    }

    /*** {android/view/ViewRootImpl.java}**/
    private void draw(boolean fullRedrawNeeded) {
        if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
            return;
        }
    }

    /*** {android/view/ViewRootImpl.java}**/
    private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
                                 boolean scalingRequired, Rect dirty) {
        // 执行到根布局view了 就可以往下分发了
        mView.draw(canvas);
    }

    /*** {android/view/ViewRootImpl.java}**/
    public void draw(Canvas canvas) {
        // 画背景
        if (!dirtyOpaque) {
            drawBackground(canvas);
        }
        if (!verticalEdges && !horizontalEdges) {
            // 回调 onDraw()
            if (!dirtyOpaque) onDraw(canvas);
            // 分发 draw()
            dispatchDraw(canvas);
            // 绘制 foreground
            onDrawForeground(canvas);
            return;
        }
        // ... 后面情况也是这几个步骤
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容