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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容