Window和WindowManager知识点深入解析

关键字:Window WindowManager Android

转载请注明链接:http://blog.csdn.net/feather_wch/article/details/79186967

  1. 以面试题形式总结Window、WindowManager所有知识点
  2. 总结Window和WindowManager的基本使用以及概念
  3. 分析Window的内部机制
  4. 分析Activity、Dialog、Toast的Window创建过程

Window和WindowManager

版本:2018/2/13-1


1、Window是什么?

  1. 表示一个窗口的概念,是所有View的直接管理者,任何视图都通过Window呈现(单击事件由Window->DecorView->View; Activity的setContentView底层通过Window完成)
  2. Window是一个抽象类,具体实现是PhoneWindow
  3. 创建Window需要通过WindowManager创建
  4. WindowManager是外界访问Window的入口
  5. Window具体实现位于WindowManagerService
  6. WindowManagerWindowManagerService的交互是通过IPC完成

2、如果通过WindowManager添加Window(代码实现)?

        //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);
  1. 注意一定要指定布局类型layoutParams.type
  2. 需要动态申请Draw over other apps权限:http://blog.csdn.net/feather_wch/article/details/79185045

3、LayoutParams的flags属性

Flags解释
FLAG_NOT_FOCUSABLE表示Window不需要焦点,会同时启用FLAG_NOT_TOUCH_MODAL, 最终事件会直接传递到下层具有焦点的Window
FLAG_NOT_TOUCH_MODEL将当前Window区域以外的单击事件传递给底层Window,当前区域内的单击事件自己处理(如果不开启,其他Window会无法收到单击事件)
FLAG_SHOW_WHEN_LOCKED可以让Window显示在锁屏的界面上

4、LayoutParams的type属性

Window类型含义Window层级Type参数
应用Window对应着一个Activity1~99(视图最下层)
子Window不能单独存在,需要附属在特定的父Window之中(如Dialog就是子Window)1000~1999
系统Window需要声明权限才能创建的Window,比如Toast系统状态栏2000~2999(视图最上层)TYPE_SYSTEM_OVERLAY / TYPE_SYSTEM_ERROR

需要在AndroidManifest中声明权限:SYSTEM_ALERT_WINDOW

5、WindowManager的三个主要功能:添加、更新、删除View

public interface ViewManager
{
    public void addView(View view, ViewGroup.LayoutParams params); //添加View
    public void updateViewLayout(View view, ViewGroup.LayoutParams params); //更新View
    public void removeView(View view); //删除View
}

6、通过WindowManager实现拖动View的效果

  1. View设置onTouchListener监听器
  2. onTouch方法中根据当前坐标,来更新ViewupdateViewLayout
mButton.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        switch (event.getAction()){
            case MotionEvent.ACTION_MOVE:
                mLayoutParams.x = rawX;
                mLayoutParams.y = rawY;
                mWindowManager.updateViewLayout(mButton, mLayoutParams);
                break;
        }
        return false;
    }
});

Window的内部机制

7、Window概念解析

  1. Window和View通过ViewRootImpl建立联系
  2. Window并不是实际存在的,而是以View的形式存在
  3. WindowManager的三个接口方法也是针对View
  4. 实际使用中无法直接访问Window,必须通过WindowManager
  5. View是视图的呈现方式,但是不能单独存在,必须依附在Window这个抽象的概念上

8、Window的添加过程addView

  1. WindowManager是一个接口,真正实现类是WindowManagerImpl,并最终以代理模式交给WindowManagerGlobal实现
//WindowManagerImpl中的三大方法都交给WindowManangerGlobal实现
        public void addView(View view, ViewGroup.LayoutParams params) {
            applyDefaultToken(params);
            mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
        }
        public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
            applyDefaultToken(params);
            mGlobal.updateViewLayout(view, params);
        }
        public void removeView(View view) {
            mGlobal.removeView(view, false);
        }
  1. WindowManagerGlobalsetView会通过ViewRootImplsetView建立ViewWindow的联系
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
        //1. 检查参数是否合法
        if (view == null) { throw new IllegalArgumentException("view must not be null");}
        if (display == null) { throw new IllegalArgumentException("display must not be null");}
        if (!(params instanceof WindowManager.LayoutParams)) {throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");}
        //2. 如果是子Window会调整布局参数
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
        if (parentWindow != null) {
            parentWindow.adjustLayoutParamsForSubWindow(wparams);
        } else {
            //3. 如果没有父Window则根据该app的硬件加速设置,设置给该View
            ...
        }
        synchronized (mLock) {
            //...省略....
            //4. 创建Window所对应的ViewRootImpl
            ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
            //5. 将Window对应的ViewRootImpl、View、布局参数添加到列表中
            view.setLayoutParams(wparams);
            mViews.add(view);//将Window对应的View添加到列表中
            mRoots.add(root);//将ViewRootImpl添加到列表中
            mParams.add(wparams);//将Window对应的布局参数添加到列表中
            //6. 通过ViewRootImpl完成View的绘制过程,以及Window的添加过程
            try {
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                //...
            }
        }
    }
  1. 通过ViewRootImpl的setView完成View的绘制过程,以及Window的添加过程
//ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    ...
    //1. 完成异步刷新请求-进行View绘制
    requestLayout();
    ...
    //2. WindowSession的类型是IWindowSession,Binder对象(IPC调用),真正实现类是Session
    res = mWindowSession.addToDisplay(mWindow, ...);
    ...
}
//ViewRootImpl.java: 完成异步刷新请求(绘制View)
public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        checkThread();
        mLayoutRequested = true;
        //1. 实际是View绘制的入口(测量、布局、重绘)
        scheduleTraversals();
    }
}
//Session.java
public int addToDisplay(IWindow window, ...) {
    //通过`WindowManagerService`实现Window的添加
    return mService.addWindow(this, window, ...);
}

9、Window的删除过程removeView
如同addView一样最终由WindowManagerGlobal实现:

    //WindowManagerImpl.java
    public void removeView(View view) {
        mGlobal.removeView(view, false);
    }
    //WindowManagerGlobal.java
    public void removeView(View view, boolean immediate) {
        ...
        synchronized (mLock) {
            //1. 查询待删除的View的索引
            int index = findViewLocked(view, true);
            View curView = mRoots.get(index).getView();
            //2. 进行进一步删除
            removeViewLocked(index, immediate);
            ...
        }
    }
    //WindowManagerGlobal.java
    private void removeViewLocked(int index, boolean immediate) {
        ViewRootImpl root = mRoots.get(index);
        View view = root.getView();
        ...
        //1. ViewRoot调用die,发送删除请求后立即返回,此时View并没有完成删除
        boolean deferred = root.die(immediate);
        if (view != null) {
            view.assignParent(null);
            //2. 将View添加到等待删除的列表中
            if (deferred) {
                mDyingViews.add(view);
            }
        }
    }
    //ViewRootImpl.java
    boolean die(boolean immediate) {
        //1. 如果是同步删除,直接调用doDie
        if (immediate && !mIsInTraversal) {
            doDie();
            return false;
        }
        //2. 如果是异步删除,发送消息。最终由Handler接收并且调用`doDie()`
        mHandler.sendEmptyMessage(MSG_DIE);
        return true;
    }
    //ViewRootImpl.java: 同步删除
    void doDie() {
        ...
        synchronized (this) {
            //1. 删除`view`
            dispatchDetachedFromWindow();
            ...
        }
        //2. 刷新数据,将Window对应的所有对象从列表中删除
        WindowManagerGlobal.getInstance().doRemoveView(this);
    }

    //ViewRootImpl.java: 删除View
    void dispatchDetachedFromWindow() {
        /**=================================
         * 1. 调用View的dispatchDetachedFromWindow
         *  -内部会调用onDetachedFromWindow和onDetachedFromWindowInternal
         *  -onDetachedFromWindow()在View删除时调用,可以进行:终止动画和线程等操作
         *=================================*/
        if (mView != null && mView.mAttachInfo != null) {
            mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);
            mView.dispatchDetachedFromWindow();
        }
        //2. 【IPC】调用`Session`的方法删除`Window`, 最终调用WMS的`removeWindow()`
        mWindowSession.remove(mWindow);
        ......
    }

WindowManager中提供了两种删除接口:removeView异步删除、removeViewImmediate同步删除(不建议使用)

11、Window的更新过程updateViewLayout

    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
        ...
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
        //1. 给View设置新布局
        view.setLayoutParams(wparams);
        //2. 按照index从列表中删除旧布局,并添加新布局
        synchronized (mLock) {
            int index = findViewLocked(view, true);
            ViewRootImpl root = mRoots.get(index);
            mParams.remove(index);
            mParams.add(index, wparams);
            //3. 更新ViewRootImpl中的布局(会对View进行测量、布局、重绘,)
            root.setLayoutParams(wparams, false);
        }
    }
  1. 和添加删除类似,最终调用WindowManagerGlobalupdateViewLayout方法
  2. root.setLayoutParams会对View进行重新布局——测量、布局、重绘
  3. root.setLayoutParams还会通过WindowSession更新Window的视图——最终通过WindowManagerServicerelayoutWindow()实现(IPC)

Window的创建过程

12、Activity的启动过程
启动最终由主线程(ActivityThread)的handleLaunchActivity()处理:

    //ActivityThread.java : 处理Activity的创建
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        //1. 创建Activity前进行初始化
        WindowManagerGlobal.initialize();
        //2. 完成整个启动过程
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
            //3. 内部调用onResume()
            handleResumeActivity(r.token, false, r.isForward, ......);
            ......
        }
        ......
    }
    //ActivityThread.java
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        //1. 创建Context
        ContextImpl appContext = createBaseContextForActivity(r);
        //2. 类加载器创建Activity
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
        //3. 创建Application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        //4. window
        Window window = null;
        if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
            window = r.mPendingRemoveWindow;
            ...
        }
        //5.  给Activity关联Context、创建所属于的Window对象并设置回调接口
        activity.attach(appContext, this, ...,window, ...);
        //6. 调用onCreate()-最终完成整个启动过程
        if (r.isPersistable()) {
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
        return activity;
    }
    //Activity.java
    final void attach(Context context, ..., Window window, ...) {
        //1. 创建PhoneWindow
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        /**=======================================================
         * 2. `Activity`实现了`window`的`callback接口`
         * -外界状态改变时会回调Activity的方法:
         *   -dispatchTouchEvent(处理屏幕点击事件)
         *   -onAttachedToWindow(window被关联到WindowManager时调用)
         *   -...
         *=========================================================*/
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        ...
        //3. 建立Window和WindowManager的联系
        mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE), ...);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
        ...
    }
    //Window.java内部接口:
    public interface Callback {
        //1. 事件分发机制源头
        public boolean dispatchTouchEvent(MotionEvent event);
        public boolean dispatchKeyEvent(KeyEvent event);
        public void onAttachedToWindow();
        public void onDetachedFromWindow();
        ......
    }

13、* 老版Window对象的创建是通过PolicyManagermakeNewWindow方法实现:

  1. PolicyManager是一个策略类
  2. Activity的Window就是通过PolicyManager的一个工厂方法创建
  3. PolicyManager实现的工厂方法全部在策略接口IPolicy中声明
  4. PolicyManager的实现类是Policy
//Window的实现类就是`PhoneWindow`
public Window makeNewWindow(Context context){
  return new PhoneWindow(context);
}

14、Activity的视图附加到Window的流程分析(setContentView)

//Activity.java
public void setContentView(View view) {
    //通过PhoneWindow的setContentView
    getWindow().setContentView(view);
    initWindowDecorActionBar();
}
//PhoneWindow.java
public void setContentView(int layoutResID) {
    //1. 创建DecorView
    if (mContentParent == null) {
        installDecor();
    }
    //2. 将Activity视图添加到mContentParent中(android.R.id.content)
    mLayoutInflater.inflate(layoutResID, mContentParent);
    /**========================================
     * 3. 回调Activity的onContentChanged()方法
     *  -用于通知Activity视图发生改变
     *  -onContentChanged()是空实现可以自定义处理
     *========================================*/
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
    ...
}
//PhoneWindow.java
private void installDecor() {
    mForceDecorInstall = false;
    //1. DecorView不存在, 则创建
    if (mDecor == null) {
        mDecor = generateDecor(-1);
        ...
    } else {
        //2. DecorView存在,则与PhoneWindow关联
        mDecor.setWindow(this);
    }
    //3. 加载具体布局文件,到DecorView中
    if (mContentParent == null) {
        mContentParent = generateLayout(mDecor);
        ...
    }
}
/**=============================================================
 *               `DecorView`的真正显示过程
 * -通过onCreate()仅仅是将`Activity`的布局添加到`DecorView`
 * -`DecorView`添加到`Window`中后才能真正显示出来
 * -`DecorView`是在主线程的handleResumeActivity()中添加到Window并显示
 * //ActivityThread.java
 *=============================================================*/
final void handleResumeActivity(IBinder token, ...) {
    //1. onResume()
    r = performResumeActivity(token, clearHide, reason);
    //2. 完成`DecorView`的添加和显示两个过程
    r.activity.makeVisible();
    ...
}
//Activity.java
void makeVisible() {
    //1. 将`DecorView`添加到`Window`中(通过WindowManager)
    if (!mWindowAdded) {
        ViewManager wm = getWindowManager();
        wm.addView(mDecor, getWindow().getAttributes());
        mWindowAdded = true;
    }
    //2. 将DecorView显示出来
    mDecor.setVisibility(View.VISIBLE);
}

Dialog

15、Dialog的Window创建过程详解
Dialog的使用:

AlertDialog alertDialog = new AlertDialog.Builder(this).setTitle("AlerDialog!").create();
alertDialog.show();

Dialog的流程源码:

//Dialog.java: 显示Dialog
public void show() {
    if (mShowing) {
        if (mDecor != null) {
            //1. 如果对应DecorView已经存在,直接显示
            mDecor.setVisibility(View.VISIBLE);
        }
        return;
    }
    //2. 获取DecorView
    mDecor = mWindow.getDecorView();
    //3. 通过WM的addView将Dialog进行显示
    WindowManager.LayoutParams l = mWindow.getAttributes();
    mWindowManager.addView(mDecor, l);
    ...
}

16、Dialog的销毁流程分析

//Dialog.java
public void dismiss() {
    //1. 线程安全,最终都在主线程移除该Dialog
    if (Looper.myLooper() == mHandler.getLooper()) {
        dismissDialog();
    } else {
        mHandler.post(mDismissAction);
    }
}
//Dialog.java
void dismissDialog() {
    //1. 移除Window
    mWindowManager.removeViewImmediate(mDecor);
    ...
}
//WindowManagerImpl.java
public void removeViewImmediate(View view) {
    mGlobal.removeView(view, true);
}

17、 Dialog的注意点

  1. Dialog必须采用ActivityContext,因为需要有应用token(ApplicationContext没有应用token)
  2. 也可以将DialogWindow通过type设置为系统Window就不再需要token。
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

完整代码

//权限判断
if (Build.VERSION.SDK_INT >= 23) {
    if (!Settings.canDrawOverlays(this)) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivityForResult(intent, 1);
    } else {
        //TODO 做你需要的事情
        alertDialog = new AlertDialog.Builder(getApplicationContext()).setTitle("AlerDialog!").create();
        alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        alertDialog.show();
    }
}
//AndroidManifest.xml-没有系统权限会导致报错
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

Toast

18、Toast的内部机制介绍

  1. Toast也是基于Window来实现的
  2. Toast具有定时取消功能,系统采用Handler实现
  3. Toast内部有两类IPC过程:1-Toast访问NotificationManagerService;2-NotificationManagerService回调ToastTN接口

19、Toast的show()方法原理分析

/**
 * Toast.java中显示和隐藏都是IPC过程
 */
public void show() {
    if (mNextView == null) {
        throw new RuntimeException("setView must have been called");
    }
    //1. 获取NotificaitonMnagerService
    INotificationManager service = getService();
    String pkg = mContext.getOpPackageName();
    //2. TN是Binder类,NotificationManagerService处理Toast显示时,会跨进程回调TN中的方法
    //3. TN运行在Binder线程池中,需要通过Hanlder将其切换到(发送Toast请求的)线程中
    //4. 使用Hanlder意味着Toast无法在没有Looper的线程中弹出
    TN tn = mTN;
    tn.mNextView = mNextView;
    try {
        //5. NotificationManagerService进行toast
        service.enqueueToast(pkg, //当前应用包名
                tn,
                mDuration);
    } catch (RemoteException e) {
        // Empty
    }
}

//NotificationManagerService
public void enqueueToast(String pkg, ITransientNotification callback, int duration)
{
    ...参数合法性判断...
    ...省略...
    synchronized (mToastQueue) {
        .......
        try {
            //1. 将Toast请求封装为`ToastRecord`
            ToastRecord record;
            int index = indexOfToastLocked(pkg, callback);
            //2. 如果ToastRecord已经在队列中(mToastQueue),则直接更新
            if (index >= 0) {
                record = mToastQueue.get(index);
                record.update(duration);
            } else {
                /**=================================================================
                 *3. 限制非系统应用,队列最多能存50个(MAX_PACKAGE_NOTIFICATIONS)。
                 *   防止DOS(Denail of Service)攻击:
                 *    如果一个应用大量连续弹出Toast,会导致其他应用没有机会弹出Toast
                 *===============================================================*/
                if (!isSystemToast) {
                    int count = 0;
                    final int N = mToastQueue.size();
                    for (int i=0; i<N; i++) {
                        final ToastRecord r = mToastQueue.get(i);
                        if (r.pkg.equals(pkg)) { //同一个包
                            count++;
                            if (count >= MAX_PACKAGE_NOTIFICATIONS) {
                                Slog.e(TAG, "Package has already posted " + count
                                        + " toasts. Not showing more. Package=" + pkg);
                                return;
                            }
                        }
                    }
                }
                //4. 将Toast存放到队列中
                record = new ToastRecord(callingPid, pkg, callback, duration);
                mToastQueue.add(record);
                ......
            }
            /**===========================================================
             * 5. 用于显示当前Toast
             *  Toast显示由ToastRecord的callback(Toast的TN对象的远程Binder)完成
             *  通过CallBack调用了TN中的方法,该方法运行在Toast请求方的Binder线程池中
             *===========================================================*/
            //5. 用于显示当前Toast。
            if (index == 0) {
                showNextToastLocked(); //Toast显示由ToastRecord的callback(Toast的TN对象的远程Binder)完成
            }
        } finally {
            Binder.restoreCallingIdentity(callingId);
        }
    }
}

//NotificationManagerService.java
void showNextToastLocked() {
    ToastRecord record = mToastQueue.get(0);
    while (record != null) {
         ...省略...
        try {
            //1. 跨进程调用Toast中TN内部的show()方法进行展示
            record.callback.show();
            /**===========================================================
             * 2. 会发送一个延时消息(取决于Toast的时长)。
             *  1-Message最终会由NotificationMaService中的WorkerHandler处理
             *  2-调用handleTimeout->cancelToastLocked->`record.callback.hide();
             *  3-最终调用TN中的hide方法并且将ToastRecord从队列中移除
             *===========================================================*/
            scheduleTimeoutLocked(record);
            return;
        } catch (RemoteException e) {
            ...省略...
        }
    }
}

20、Toast的cancel()方法原理分析

  1. 内部调用NotificationManagerService的cancelToast方法()
  2. cancelToast方法()->cancelToastLocked()->record.callback.hide();
  3. record.callback.hide()通过IPC调用TN中的hide方法
  4. 最后将ToastRecord移除队列
//Toast.java
public void cancel() {
    mTN.hide();

    try {
        getService().cancelToast(mContext.getPackageName(), mTN);
    } catch (RemoteException e) {
        // Empty
    }
}

21、Toast的TN(Binder)内部机制

//Toast.java TN
private static class TN extends ITransientNotification.Stub {
    ...省略...
    WindowManager mWM;
    TN() { ...省略... }
    //1. 开启了mShow的Runnable
    public void show() {
        mHandler.post(mShow);
    }
    //2. 开启了mHide的Runnable
    public void hide() {
        if (localLOGV) Log.v(TAG, "HIDE: " + this);
        mHandler.post(mHide);
    }
    //3. 调用handleShow()进行显示
    final Runnable mShow = new Runnable() {
        public void run() {
            handleShow();
        }
    };
    //4. 调用handleHide()进行显示
    final Runnable mHide = new Runnable() {
        public void run() {
            handleHide();
            mNextView = null;
        }
    };
    //5. 真正完成显示功能
    public void handleShow() {
        ......
        //7. 将Toast视图添加到Window中
        mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        ......
        mWM.addView(mView, mParams);
        ......
    }
    //6. 真正完成隐藏功能
    public void handleHide() {
        if (mView != null) {
            //8. 将Toast视图从Window中移除
            if (mView.getParent() != null) {
                mWM.removeView(mView);
            }
            mView = null;
        }
    }
    private void trySendAccessibilityEvent() {
        ......
    }
}

Window源码流程图

22、WindowManager的addView工作流程:

Created with Raphaël 2.1.2 WindowManagerService WindowManagerService Session Session WindowManager WindowManager WindowManagerGlobal WindowManagerGlobal ViewRootImpl ViewRootImpl 1.WM本身为接口 继承自ViewManager 2.实现类: WindowManagerImpl 3.mGlobal.addView() 4.(3)new ViewRootImpl() 5.(3)将ViewRootImpl View 布局参数 添加到列表中 6.(3)root.setView() 7.(6)requestLayout() 8.(7)scheduleTraversals() -绘制三大流程的入口 9.(6)mWindowSession.addToDisplay(mWindow, ...) 【IPC】10.mService. addWindow(...);

23、Window的removeView()流程分析:

Created with Raphaël 2.1.2 WindowManagerGlobal WindowManagerGlobal ViewRootImpl ViewRootImpl WindowManagerService WindowManagerService 1. 查询View的索引 2. removeViewLocked() 3. root.die() 4. 将View添加到 等待删除列表中 5. 同步删除: doDie() 6. 异步删除: mHandler. sendEmptyMessage(MSG_DIE) 7.(5)dispatchDetachedFromWindow() 8.(5)WindowManagerGlobal. doRemoveView(this) 9.(7)mView. dispatchDetachedFromWindow() 【IPC】10.(7)mWindowSession. remove(mWindow) 11.removeWindow()

24、Activity从创建到显示的工作流程:

Created with Raphaël 2.1.2 ActivityThread ActivityThread Activity Activity PhoneWindow PhoneWindow 1. handleLaunchActivity() 2. performLaunchActivity() 3.(2) 创建Context 4.(2) 创建Activity 5.(2) 创建Application 6.(2) activity.attach() 7.(2) mInstrumentation. callActivityOnCreate() 8.(6) new PhoneWindow() 9.(6) 给Window设置 Activity的回调: dispatchTouchEvent... 10.(6) mWindow. setWindowManager() 11.(7) onCreate() 12. setContentView() 13. getWindow(). setContentView(view) 14. installDecor() 15. mLayoutInflater. inflate(layoutResID, mContentParent) 16. cb.onContentChanged() 17.(14) generateDecor(-1) 18.(14) generateLayout(mDecor) 19. handleResumeActivity() 20(19) performResumeActivity() 21(19) activity.makeVisible() 22.wm.addView(mDecor...) 23.mDecor.setVisibility()
  1. 建立Window和WindowManager联系:
    mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE), ...);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值