Android WMS流程

WMS流程

Window & Activity & DecorView & ViewRoot关系

  • Activity:
    • 处理器,控制生命周期和处理事件
    • 1个Activity包含1个Window
    • 通过回调与Window、View交互
  • Window:
    • 实现类是PhoneWindow
    • 视图的承载器,用于管理View的显示
    • PhoneWindow内部包含一个DecorView
    • 内部通过WindowManager管理UI,将DecorView交给ViewRoot
  • DecorView:
    • 顶层View,本质是FrameLayout
    • 显示和加载布局
    • View的事件最先经过DecorView,再分发到子View
  • ViewRoot:
    • ViewRootImpl是其实现类
    • 用于连接WindowManagerDecorView
    • 完成View的三大流程:测量、布局、绘制

在这里插入图片描述

在这里插入图片描述

流程图

在这里插入图片描述

源码分析

ActivityThread#handleLaunchActivity()

  • 初始化WMS服务
  • 调用performLaunchActivity()
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    
    
  
    //初始化WMS服务
    WindowManagerGlobal.initialize();
    
    //调用performLaunchActivity()初始化Activity
    final Activity a = performLaunchActivity(r, customIntent);

    return a;
}

ActivityThread#performLaunchActivity()

  • 创建Activity
  • 调用Activity#attach()
  • 回调Activity#onCreate()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    
    
    Activity activity = null;
    try {
    
    
        //创建Activity
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(
            cl, component.getClassName(), r.intent);
    } catch (Exception e) {
    
           
    }


    if (activity != null) {
    
    
        //调用Activity#attach(),初始化Activity
        activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken);


        //callActivityOnCreate()方法最终调用Activity#onCreate()
        activity.mCalled = false;
        if (r.isPersistable()) {
    
    
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
    
    
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
    }
    return activity;
}

Activity#attach()

  • 创建PhoneWindow对象,PhoneWindow是Window的实现类
  • 创建WindowManageImpl,WindowManageImpl是WindowManage的实现类
final void attach(Context context, ActivityThread aThread,
                  Instrumentation instr, IBinder token, int ident,
                  Application application, Intent intent, ActivityInfo info,
                  CharSequence title, Activity parent, String id,
                  NonConfigurationInstances lastNonConfigurationInstances,
                  Configuration config, String referrer, IVoiceInteractor voiceInteractor,
                  Window window, ActivityConfigCallback activityConfigCallback, 
                  IBinder assistToken) {
    
    
    
    attachBaseContext(context);

    //创建PhoneWindow
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    mWindow.setWindowControllerCallback(mWindowControllerCallback);
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);

    //设置软键盘
    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
    
    
        mWindow.setSoftInputMode(info.softInputMode);
    }

    //在Window#setWindowManager()中创建WindowManager
    mWindow.setWindowManager(
        (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
        mToken, mComponent.flattenToString(),
        (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    if (mParent != null) {
    
    
        mWindow.setContainer(mParent.getWindow());
    }
    mWindowManager = mWindow.getWindowManager();
}

Activity#setContentView()

  • 最终调用PhoneWindow#setContentView()
@Override
public void onCreate(Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

public void setContentView(@LayoutRes int layoutResID) {
    
    
    //最终调用PhoneWindow#setContentView()
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

PhoneWindow#setContentView()

  • 创建DecorView
  • 将Activity的XML布局加载到DecorView中
public void setContentView(int layoutResID) {
    
    
    /*
    mContentParent为DecorView里的内容栏
    当mContentParent==null时,会调用installDecor()创建一个DecorView;
    当mContentParent!=null时,会删除所有子View
    */
    if (mContentParent == null) {
    
    
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
    
    
        mContentParent.removeAllViews();
    }

    //加载解析XML布局,并添加到mContentParent内容栏里
    mLayoutInflater.inflate(layoutResID, mContentParent);

    //内容发生变化通知回调
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
    
    
        cb.onContentChanged();
    }
}

PhoneWindow#installDecor()

private void installDecor() {
    
    
    mForceDecorInstall = false;
    if (mDecor == null) {
    
    
        //创建DecorView
        mDecor = generateDecor(-1);
    } else {
    
    
        mDecor.setWindow(this);
    }
    if (mContentParent == null) {
    
    
        //为DecorView设置布局格式
        mContentParent = generateLayout(mDecor);
    }
}

//创建DecorView
protected DecorView generateDecor(int featureId) {
    
    
    return new DecorView(context, featureId, this, getAttributes());
}

//为DecorView设置布局格式
//DecorView本质是一个FrameLayout里面包含:TitleView和ContentView
protected ViewGroup generateLayout(DecorView decor) {
    
    
    //从主题文件中获取样式信息
    TypedArray a = getWindowStyle();
    //根据主题样式,加载窗口布局
    int layoutResource;
    int features = getLocalFeatures();
    //加载layoutResource
    View in = mLayoutInflater.inflate(layoutResource, null);

    //往DecorView中添加子View
    decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); 
    mContentRoot = (ViewGroup) in;

    //这里获取的是mContentParent = 即为内容栏(content)对应的DecorView = FrameLayout子类
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); 
    return contentParent;
}

ActivityThread#handleResumeActivity()

  • 回调Activity#onResume()
  • 获取PhoneWindow和DecorView,将Activity与DecorView绑定
  • 调用WindowManageImpl#addView()将DecorView传入
public void handleResumeActivity(IBinder token, boolean finalStateRequest, 
                                 boolean isForward, String reason) {
    
    

    //最终会调用Activity#onResume()
    final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);

    final Activity a = r.activity;

    if (r.window == null && !a.mFinished && willBeVisible) {
    
    
        //获取PhoneWindow对象
        r.window = r.activity.getWindow();
        //获取DecorView对象
        View decor = r.window.getDecorView();
        
        //DecorView不可见
        decor.setVisibility(View.INVISIBLE);
        ViewManager wm = a.getWindowManager();
        WindowManager.LayoutParams l = r.window.getAttributes();
        
        //DecorView与Activity建立关联
        a.mDecor = decor;

        if (a.mVisibleFromClient) {
    
    
            if (!a.mWindowAdded) {
    
    
                a.mWindowAdded = true;
                //调用WindowManageImpl#addView()
                wm.addView(decor, l);
            } 
        }
    } 

    if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
    
    
        if (r.activity.mVisibleFromClient) {
    
    
            //这时候DecorView才可见
            r.activity.makeVisible();
        }
    }
}

WindowManagerImpl#addView()

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    
    
    //WindowManagerGlobal#addView()    
    mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
                    mContext.getUserId());
}

WindowManagerGlobal#addView()

  • 创建ViewRootImpl
  • 将DecorView交给ViewRootImpl处理
public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow, int userId) {
    
    

    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    if (parentWindow != null) {
    
    
        parentWindow.adjustLayoutParamsForSubWindow(wparams);
    } else {
    
    
        final Context context = view.getContext();
        if (context != null
                && (context.getApplicationInfo().flags
                        & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
    
    
            wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
        }
    }

    ViewRootImpl root;
    synchronized (mLock) {
    
        
        //创建ViewRootImpl
        root = new ViewRootImpl(view.getContext(), display);
        view.setLayoutParams(wparams);
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
        try {
    
    
            //调用ViewRootImpl#setView()
            root.setView(view, wparams, panelParentView, userId);
        } catch (RuntimeException e) {
    
    
        }
    }
}

ViewRootImpl#setView()

  • ViewRootImpl最终会触发遍历操作
  • 依次执行View的测量、布局、绘制流程
public void setView(View view, WindowManager.LayoutParams attrs, 
                    View panelParentView, int userId) {
    
    
    requestLayout();        
}

ViewRootImpl#requestLayout()

public void requestLayout() {
    
    
    if (!mHandlingLayoutInLayoutRequest) {
    
    
        //检查是否在主线程,否则抛出异常
        checkThread();
        mLayoutRequested = true;
        scheduleTraversals();
    }
}

void scheduleTraversals() {
    
    
    if (!mTraversalScheduled) {
    
    
        mTraversalScheduled = true;
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        mChoreographer.postCallback(
            Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        notifyRendererOfFramePending();
        pokeDrawLockIfNeeded();
    }
}

final class TraversalRunnable implements Runnable {
    
    
    @Override
    public void run() {
    
    
        doTraversal();
    }
}

ViewRootImpl#doTraversal()

  • 最终调用ViewRootImpl#performTraversals()
void doTraversal() {
    
      
    //最终调用View的measure、layout、draw流程
    performTraversals();
}

ViewRootImpl#performTraversals()

  • 依次调用performMeasure() / performLayout() / performDraw() 完成View的三大流程
private void performTraversals() {
    
    

    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

    performLayout(lp, mWidth, mHeight);

    /*		
    viewTreeObserver.addOnGlobalLayoutListener(object:ViewTreeObserver.OnGlobalLayoutListener{
            override fun onGlobalLayout() {
               //可以在这里获取View的宽高
            }
    })
    */
    mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();

    performDraw();
}

ViewRootImpl#performMeasure()

private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
    
    
    if (mView == null) {
    
    
        return;
    }

    mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}

ViewRootImpl#performLayout()

private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
                           int desiredWindowHeight) {
    
    
    final View host = mView;
    if (host == null) {
    
    
        return;
    }

    host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
}

ViewRootImpl#performDraw()

private void performDraw() {
    
    
    boolean canUseAsync = draw(fullRedrawNeeded);
}

private boolean draw(boolean fullRedrawNeeded) {
    
    
    drawSoftware(surface, mAttachInfo, xOffset, yOffset,
                 scalingRequired, dirty, surfaceInsets)
}

private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
                             boolean scalingRequired, Rect dirty, Rect surfaceInsets) {
    
    
    mView.draw(canvas);
}

总结

  • 在performLaunchActivity阶段,会创建Activity、PhoneWindow、WindowManageImpl,并回调Activity#onCreate(),接着执行setContentView流程,创建DecorView并将XML布局解析加载到DecorView中。
  • 在handleResumeActivity阶段,会调用Activity#onResume(),将Activity与DecorView建立关联,创建ViewRootImpl,将DecorView交给ViewRootImpl处理,最终ViewRootImpl依次执行View的三大流程。

常见问题

invalidate和requestLayout区别

  • requestLayout:requestLayout会直接递归调用父View的requestLayout,直到ViewRootImpl,然后触发ViewRoomtImpl的peformTraversals()方法,会依次调用onMeasure()onLayout(),不一定会触发onDraw();当在layout过程中发现四个顶点(left、top、right、bottom)和以前不一样时,会触发invalidate,调用onDraw,进行重新绘制。
  • invalidate:View的invalidate不会触发ViewRootImpl的invalidate,而是递归调用父View的invalidateChildParent,知道ViewRootImpl的invalidateChildParent,然后触发perfromTraversals,由于mLayoutRequested为false,不会调用onMeasure和onLayout,只会调用onDraw,ViewGroup的onDraw不会被调用(除非设置背景),倒置当前View被重绘。

Guess you like

Origin blog.csdn.net/qq_14876133/article/details/100103907