Activity页面加载流程(二)

接上一篇《Activity页面加载流程(一)》

上一篇讲了Window的创建,但其显示流程还没有讲清楚就跑路了

废话不多说,我们continue
PS:英文用错了场景别笑话,谁让它是关键词字😊😊
        这个单词拼不成汉语吧😊😊

WindowManager、WindowManagerImpl和WindowManagerGlobal的关系及内部机制

WindowManager是一个继承于ViewManager的接口,实现类是WindowManagerImpl

Activity.java

final void attach(...){
  ...
  mWindow.setWindowManager(
  (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),  //系统的WindowManger
        mToken, mComponent.flattenToString(),
        (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
  ...
  mWindowManager = mWindow.getWindowManager();
}

Window.java

public void setWindowManager(WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) {
  ...
  //wm的createLocalWindowManager方法又重新new了WindowManagerImpl
  mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}

public WindowManager getWindowManager() {
  return mWindowManager;
}

WindowManagerImpl.java
WindowManagerImpl是WindowManager的实现类,显实现了addView、updateViewLayout、removeView等方法,可是这哥们胸怀宇宙,有空还要看星星,别看它是一个实现类,名字还带一个Impl,却把具体工作都交给了单例的WindowManagerGlobal。

public final class WindowManagerImpl implements WindowManager {
  //全局单例
  private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

  ...
  @Override
  public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
  }

  @Override
  public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.updateViewLayout(view, params);
  }

  @Override
  public void removeView(View view) {
    mGlobal.removeView(view, false);
  }
  ...
}

WindowManagerGlobal.java
WindowManagerGlobal是单例的,所以它内部用几个集合来保存Window及参数和所对应的View

//每个Window对应的View
private final ArrayList<View> mViews = new ArrayList<View>();
//每个Window对应的ViewRootImpl
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
//每个Window的参数
private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>();
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {

  ViewRootImpl root;
  ...
  //创建ViewRootImpl,View的invalidate更新view的时候,就是从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 {
    //重要方法
    root.setView(view, wparams, panelParentView);
  }
  ...
}

Window的显示

WindowManagerService作为一个系统级的服务运行在一个单独的进程,所以WindowManager和它之间的交互是一个IPC(进程间通信)过程,ViewRootImpl充当了桥梁的作为

通过Binder机制获取WMS,在WindowManagerService获取舒适化Session,进而通过session的addToDisplay方法和WMS的addWindow添加到将Window添加到设备

ViewRootImpl.java

final IWindowSession mWindowSession;

public ViewRootImpl(Context context, Display display) {
  ...
  //在构造方法里调用WindowManagerGlobal的static方法getWindowSession()初始化IWindowSession
  mWindowSession = WindowManagerGlobal.getWindowSession();
  ...
}

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
  ...
  //开始View的三大流程,测量、布局和绘制
  requestLayout();
  ...
  try {
    ...
    //显示
    res = mWindowSession.addToDisplay(mWindow,  ...);
    ...
  } 
  ...
}

WindowManagerGlobal.java

public static IWindowSession getWindowSession() {
  synchronized (WindowManagerGlobal.class) {
    if (sWindowSession == null) {
      try {
        InputMethodManager imm = InputMethodManager.getInstance();
        IWindowManager windowManager = getWindowManagerService();
        //从WindowManagerService里获取WindowSession
        sWindowSession = windowManager.openSession(
          new IWindowSessionCallback.Stub() {
            @Override
            public void onAnimatorScaleChanged(float scale) {
              ValueAnimator.setDurationScale(scale);
            }
          },
          imm.getClient(), imm.getInputContext());ffgetWindowManagerService
      } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
      }
    }
  return sWindowSession;
  }
}

public static IWindowManager getWindowManagerService() {
  synchronized (WindowManagerGlobal.class) {
    if (sWindowManagerService == null) {
      //从binder里获取WindowManagerService
      sWindowManagerService = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
      try {
        if (sWindowManagerService != null) {
          ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
        }
      } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
      }
    }
  return sWindowManagerService;
  }
}

WindowManagerService.java

@Override
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext) {
  if (client == null) throw new IllegalArgumentException("null client");
  if (inputContext == null) throw new IllegalArgumentException("null inputContext");
  //Session就在这里创建,Session和WindowManagerService相互持有
  Session session = new Session(this, callback, client, inputContext);
  return session;
}

Session.java

@Override
public int addToDisplay(IWindow window, ...) {
  //这里调用WMS的addWindow方法
  return mService.addWindow(this, window, ...);
}

Window已经显示了
Activity的页面加载流程已经结束,涉及到的类比较多,可能有说的不明的或错误的地方,请谅解

源码一个class动辄万行,内部类N多个
是不是脑壳疼
疼就对了
不然你以为你zou是谷歌开发工程师了


不进则退
学习还是必须的
没有什么比自身的强大更重要
你想要的
时间都会给你

学会自我约束
才能自我自由

鸡汤是给你们喝的,我喜欢吃肉

End

    原文作者:豪世_世界的世
    原文地址: https://www.jianshu.com/p/d9df86419e6a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞