笔记

  • 如何实现多线程的同步

    • volitile主要是在CPU指令禁止重排和多线程访问变量时变量发生变化时,各线程的值是同时变化的。
      只有一个线程写,其他都是读,用 volatile
    • 多个线程写,用 Synchronized
    • 多个线程写+设置超时+自行决定释放,用 ReentranLock
    • 想提高效率,不单单一个线程进入临界区,用并发包,如:ConcurrentHashMap、LinkBlockingQueue、AtomicXXX。
    • 读比写多,用 CopyOnWriteXXX
    • 希望控制线程的并发数量,用 Semaphore 信号量
    • 想让指定线程等待其他线程,用 CountDownLatch
  • Android 进程间的通信方式

20211215195246.jpg

https://zhuanlan.zhihu.com/p/149870923

  • 说说Activity加载的流程?

    • App 启动流程(基于Android8.0):
      • 点击桌面 App 图标,Launcher 进程采用 Binder IPC(具体为ActivityManager.getService 获取 AMS 实例) 向 system_server 的 AMS 发起 startActivity 请求
      • system_server 进程收到请求后,向 Zygote 进程发送创建进程的请求;
    • Zygote 进程 fork 出新的子进程,即 App 进程
    • App 进程创建即初始化 ActivityThread,然后通过 Binder IPC 向 system_server 进程的 AMS 发起 attachApplication 请求
    • system_server 进程的 AMS 在收到 attachApplication 请求后,做一系列操作后,通知 ApplicationThread bindApplication,然后发送 H.BIND_APPLICATION 消息
    • 主线程收到 H.BIND_APPLICATION 消息,调用 handleBindApplication 处理后做一系列的初始化操作,初始化 Application 等
    • system_server 进程的 AMS 在 bindApplication 后,会调用 ActivityStackSupervisor.attachApplicationLocked,之后经过一系列操作,在 realStartActivityLocked 方法通过 Binder IPC 向 App 进程发送 scheduleLaunchActivity 请求;
    • App进程的 binder 线程(ApplicationThread)在收到请求后,通过 handler 向主线程发送 LAUNCH_ACTIVITY 消息;
    • 主线程收到 message 后经过 handleLaunchActivity,performLaunchActivity 方法,然后通过反射机制创建目标 Activity;
    • 通过 Activity attach 方法创建 window 并且和 Activity 关联,然后设置 WindowManager 用来管理 window,然后通知 Activity 已创建,即调用 onCreate
    • 然后调用 handleResumeActivity,Activity 可见

附图:


app-launch.png
  • 补充:
    • ActivityManagerService 是一个注册到 SystemServer 进程并实现了 IActivityManager 的 Binder,可以通过 ActivityManager 的 getService 方法获取 AMS 的代理对象,进而调用 AMS 方法
    • ApplicationThread 是 ActivityThread 的内部类,是一个实现了 IApplicationThread 的 Binder。AMS通过 Binder IPC 经 ApplicationThread 对应用进行控制
    • 普通的 Activity 启动和本流程差不多,至少不需要再创建 App 进程了
    • Activity A 启动 Activity B,A 先 pause 然后 B 才能 resume,因此在 onPause 中不能做耗时操作,不然会影响下一个 Activity 的启动
  • Android View 深度分析requestLayout、invalidate与postInvalidate

https://blog.csdn.net/a553181867/article/details/51583060

另外,我解释一下文章里没有说明,但是很关键的一个地方:为什么方法层层向上调用时,最终会传递到ViewRootImpl中。我们知道View树的根节点是DecorView,DecorView通过WindowManagerGlobal的addView方法添加到Window中,下面是addView方法的源码:

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
   ...
   root = new ViewRootImpl(view.getContext(), display);
   view.setLayoutParams(wparams);
   ...
   mViews.add(view);
   mRoots.add(root);
   mParams.add(wparams);
   ...
   root.setView(view, wparams, panelParentView);
   ...
}

可以看到,addView方法只做了一些准备工作,最终又调用了ViewRootImpl的setView方法完成添加,看下setView方法的源码:

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
  ...
  requestLayout();
  ...
  res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
        getHostVisibility(), mDisplay.getDisplayId(),
        mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
        mAttachInfo.mOutsets, mInputChannel);
  ...
  view.assignParent(this);
}

setView方法,通过requestLayout方法绘制出View树,通过mWindowSession.addToDisplay方法向WMS注册自己,使自己可以显示到屏幕上。貌似工作都已经完成了,但是最后又调用了View的assignParent方法,看下它的源码:

void assignParent(ViewParent parent) {
    if (mParent == null) {
        mParent = parent;
    } else if (parent == null) {
        mParent = null;
    } else {
        throw new RuntimeException("view " + this + " being added, but"
                + " it already has a parent");
    }
}

这就非常明确了,DecorView调用这个方法,把ViewRootImpl设为自己的父View。所以方法调用沿着View树往上传递时,最终会传递到ViewRootImpl中。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容