android view window

2021-04-12  本文已影响0人  couriravant

两个情况,一个是DecorView,也就是activity的创建,另一种就是直接window添加view,如dialog等

Activity的启动中会有:

1。performLaunchActivity()主要做了以下几件事:

创建Activity。

创建Context。

调用Activity.attach(),创建Window,关联WindowManager。

调用Activity.onCreate()。

调用Activity.onStart()。

2.handleResumeActivity()处理的事情比较多。我总结为以下几个过程:

通过performResumeActivity()处理Activity的onRestart onResume的生命周期。

将DecorView设置为InVisible。

通过WindowManager.addView()将DecorView绘制完成。

将DecorView设置为Visiable。

通知AMS Activity启动完成。



WindowManager直接添加view的例子:

//1. 控件
        Button button = new Button(this);
        button.setText("Window Button");
        //2. 布局参数
        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT, 0, 0, PixelFormat.TRANSPARENT);
        layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
        layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
        layoutParams.x = 100;
        layoutParams.y = 300;
        // 必须要有type不然会异常: the specified window type 0 is not valid
        layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
        //3. 获取WindowManager并添加控件到Window中
        WindowManager windowManager = getWindowManager();
        windowManager.addView(button, layoutParams);

WindowManagerGlobal

public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
...
//新建ViewRootImpl
  root = new ViewRootImpl(view.getContext(), display);

            view.setLayoutParams(wparams);

            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);

            // do this last because it fires off messages to start doing things
            try {
            //调用ViewRootImpl的setview
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    } 

ViewRootImpl

 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
。。。
requestLayout();
。。
 try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
//windowsession 
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
                } catch (RemoteException e) {}
}





 @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }


 void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
//1. 实际是View绘制的入口(测量、布局、重绘)--内部通过mChoreographer去监听下一帧的刷新信号
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }



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


 //Session.java
    @Override
    public int addToDisplay(IWindow window, ...) {
        return mService.addWindow(this, window, ...);
    }

    //WindowManagerService.java
    public int addWindow(Session session, IWindow client, ...) {
        /**=================================
         * 1. 检查工作
         *    1-权限检查和设置相关
         *    2-检查是否重复添加---Binder对象会存储在HashMap<IBinder, WindowState>中
         *=================================*/
        ...
        if (mWindowMap.containsKey(client.asBinder())) {
            ...
        }
        // 2. 返回WmS中存在的对应父窗口,若不存在则返回null
        WindowState attachedWindow = windowForClientLocked(null, attrs.token, false);
        ...
        /**===========================================
         * 3. 从WmS中寻找对应的WindowToken, 并且处理合法性
         *   1-例如:对于子窗口来说,WmS中必须有对应的Token才能添加
         *   2-例如:token不为null且是应用窗口是必须要有个windowToken
 *============================================*/
        WindowToken token = mTokenMap.get(attrs.token);
        /**
         * ...检查Token合法性...
         */
        // 4. 创建窗口
        WindowState win = new WindowState(session, client, token, attachedWindow, attrs, viewVisibility);
        /**==============================================
         * 5. 额外的操作、信息保存等
         *      1. 如果是Toast,则此窗口不能够接收input事件
         *      2. Token添加到WmS中
         *      3. 窗口信息添加到WmS中
         *      4. 将窗口(WindowState)添加到Session中
         *      5. 对于应用启动时显示的窗口,设置token
         *==============================================*/
        // 1、如果是Toast,则此窗口不能够接收input事件
        mPolicy.adjustWindowParamsLw(win.mAttrs);
        // 2、从上述代码中得出是否要添加Token,若是则添加Token添加到WmS中
        if (addToken) {
            mTokenMap.put(attrs.token, token);
            mTokenList.add(token);
        }
        // 3、窗口信息添加到WmS中
        mWindowMap.put(client.asBinder(), win);
        // 4、将窗口添加到Session中
        win.attach();
        // 5、对于应用启动时显示的窗口,设置token
        token.appWindowToken.startingWindow = win;
        ...
    }

接着会通过WindowSession最终来完成Window的添加过程。在下面的代码中mWindowSession类型是IWindowSession,它是一个Binder对象,真正的实现类是Session,也就是说这其实是一次IPC过程,远程调用了Session中的addToDisPlay方法。

refer:https://blog.csdn.net/cpcpcp123/article/details/115266556

refer: https://blog.csdn.net/feather_wch/article/details/81437056

refer:https://mp.weixin.qq.com/s?__biz=MzU4NDc1MjI4Mw==&mid=2247483864&idx=1&sn=ca212f527ed4d29e1910d689f2f69b0e&chksm=fd944c2ccae3c53a36432164917d8c1d7d447204e036dd08ffb3d7fea43526ecdc8df87d0668&token=917258391&lang=zh_CN&scene=21#wechat_redirect

上一篇下一篇

猜你喜欢

热点阅读