Window相关

1、ViewRootImpl的数量

android中Window.java的唯一实现类是PhoneWindow.java,WindowManager.java的实现类是WindowManagerImpl.java,WindowManagerImpl.java中的WindowManagerGlobal用于具体操作View。WindowManagerGlobal.java添加View时会调用ViewRootImpl的setView(view, wparams, panelParentView, userId)方法,在setView方法中调用requestLayout()从而进行view的测量、布局和绘制工作。

WindowManagerGlobal.java中有三个集合mViews(保存DecorView)、mRoots(保存ViewRootImpl) 、mParams (保存WindowManager.LayoutParams)

    WindowManagerGlobal.java
    @UnsupportedAppUsage
    private final ArrayList<View> mViews = new ArrayList<View>();
    @UnsupportedAppUsage
    private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
    @UnsupportedAppUsage
    private final ArrayList<WindowManager.LayoutParams> mParams =
            new ArrayList<WindowManager.LayoutParams>();

上面三个WindowManagerGlobal.java的addView方法中添加元素,addView方法是由ActivityThread.java的handleResumeActivity方法或者Activity.java的makeVisible方法调用调用。ViewRootImpl的数量等于WindowManagerGlobal.java的addView方法被调用的次数。

在Activity、Dialog、Toast显示的时候都会执行WindowManagerGlobal.addView方法。

2、requestLayout和invalidate区别

view的requestLayout()方法最终会调用到ViewRootImpl的requestLayout()方法,接着会调用scheduleTraversals() ->mChoreographer.postCallback(

Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); ->doTraversal()从而执行测量、布局和绘制。

//ViewRootImpl.java
public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        checkThread();
        mLayoutRequested = true;
        scheduleTraversals();
    }
}

view的invalidate方法会调用ViewRootImpl的invalidateChildInParent方法,最终也会调用scheduleTraversals()->mChoreographer.postCallback(

Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); ->doTraversal(),区别是没有设置mLayoutRequested = true,mLayoutRequested 会影响measure步骤是否执行。

//ViewRootImpl.java
void invalidate() {
    mDirty.set(0, 0, mWidth, mHeight);
    if (!mWillDrawSoon) {
        scheduleTraversals();
    }
}

3、Window的添加

窗口就的添加最终在WMS中进行,ViewRootImpl作为应用层和WMS的桥梁。

WindowManagerGlobal.java添加View时会调用ViewRootImpl的setView(view, wparams, panelParentView, userId)方法,ViewRootImpl.setView调用Session的addToDisplay方法,Session.addToDisplay中会调用WMS的addWindow方法,该方法会创建WindowState对象,这就完成了应用层与WMS的IPC通信

//Session.java
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
        int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
        Rect outOutsets, InputChannel outInputChannel) {
    return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
            outContentInsets, outStableInsets, outOutsets, outInputChannel);
}

4、WindowManagerImpl和WMS区别和联系

WindowManagerImpl和WMS没有直接联系,但是二者共同处理着View的添加、更新、移除、层级属性设置等操作。WindowManagerImpl在SystemServiceRegistry的静态代码模块中创建并注册(具体可以查看文章 单例模式以及在android中的使用 ),WMS在SystemServer的startOtherServices()方法中创建并注册到ServiceManager中。

//SystemServiceRegistry.java
registerService(Context.WINDOW_SERVICE, WindowManager.class,
        new CachedServiceFetcher<WindowManager>() {
    @Override
    public WindowManager createService(ContextImpl ctx) {
        return new WindowManagerImpl(ctx);
    }});
    
//SystemServer.java
traceBeginAndSlog("StartWindowManagerService");
// WMS needs sensor service ready
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager,
        mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
        !mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
traceEnd();    

app层通过(WindowManager) context.getSystemService(Context.WINDOW_SERVICE)获取的WindowManager具体实现是WindowManagerImpl.java,具体是通过Context实现类ContextImpl.java在SystemServiceRegistry中根据名称获取已注册的服务。

//ContextImpl.java
public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this, name);
}

ViewRootImpl.setView方法会根据session调用到WMS中去完成实际的View操控动作,WMS中操作View会用到WindowState对象。

5、SurfaceFlinger的角色 

ViewRootImpl.setView方法调用了mWindowSession.addToDisplay方法,mWindowSession.addToDisplay方法调用了WMS的addWindow方法,WMS.addWindow会创建WindowState对象,然后调用WindowState的attach方法,WindowState.attach调用mWindowSession.windowAddedLocked方法,mWindowSession.windowAddedLocked方法中就会创建SurfaceSession对象,SurfaceSession对象就是window和SurfaceFlinger 连接的桥梁。

//Session.java
void windowAddedLocked(String packageName) {
    mPackageName = packageName;
    mRelayoutTag = "relayoutWindow: " + mPackageName;
    if (mSurfaceSession == null) {
        if (WindowManagerService.localLOGV) Slog.v(
            TAG_WM, "First window added to " + this + ", creating SurfaceSession");
        mSurfaceSession = new SurfaceSession();
        if (SHOW_TRANSACTIONS) Slog.i(
                TAG_WM, "  NEW SURFACE SESSION " + mSurfaceSession);
        mService.mSessions.add(this);
        if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
            mService.dispatchNewAnimatorScaleLocked(this);
        }
    }
    mNumWindow++;
}

一个SurfaceSession对象和创建多个surface,最后这些surface数据保存在Buffer中,上层app先从BufferQueue中申请Buffer,然后调用canvas.draw或者opengl.glDrawArrays(或者opengl.glDrawElements等函数) 去填充数据后再放入到BufferQueue中并通知SurfaceFlinger合成处理后就会显示当屏幕display上,所以SurfaceFlinger就是上层应用数据处理者(消费者),同时也是display数据的生产者。

6、display、surface、

无论开发者使用什么渲染 API,一切内容都会渲染到 Surface 上。Surface 表示缓冲区队列中的生产方,而缓冲区队列通常会被 SurfaceFlinger 消耗。在 Android 平台上创建的每个窗口都由 Surface 提供支持。所有被渲染的可见 Surface 都被 SurfaceFlinger 合成到屏幕。

下图显示了关键组件如何协同工作:

android.view包下的Display.java只是描述了显示屏的一些属性信息,具体实现在

DisplayManagerService

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值