0
点赞
收藏
分享

微信扫一扫

Activity布局流程+资源加载过程+插件化换肤思路


Activity布局流程

Activity框架

1.Activity里有一个window,在初始化的时候是空的,然后在activity.attach()里赋值为PhoneWindow

2.PhoneWindow里有一个DecorView,这个DecorView就是一个FrameLayout,是整个Activity的根布局

3.当新建Activity时选择不同的主题会有不同的根布局

4.比如选择的是空白的Activity,那就是分为两部分ViewStub预留和FrameLayout 这个FrameLayout就是root

5.自己写的布局就是挂在View temp下面

Activity框架

Activity布局流程+资源加载过程+插件化换肤思路_java

第4.5步:generateLayout()加载主题布局 Activity布局流程+资源加载过程+插件化换肤思路_移动开发_02

Activity布局流程+资源加载过程+插件化换肤思路_安卓_03

Activity布局流程+资源加载过程+插件化换肤思路_android_04

ActivityThread.java

先从ActivityThread.java这个类开始看

  1. performLaunchActivity(翻译 执行启动Activity)

Activity布局流程+资源加载过程+插件化换肤思路_android studio_05

在performLaunchActivity方法中

2. 先建Context 根据createBaseContextForActivity

3. 根据Context获取ClassLoader getClassLoader()

4. 根据ClassLoader 新建出一个Activity newActivity Activity布局流程+资源加载过程+插件化换肤思路_移动开发_06

补充:mInstrumentation(翻译 仪器)

这里存了activity的基本信息,创建activity啥的都在这

Activity布局流程+资源加载过程+插件化换肤思路_android_07


  1. 建了一个Window,并将它与activity关联
  2. 将Window传入了activity.attach()

Activity布局流程+资源加载过程+插件化换肤思路_移动开发_08

  1. 在activity.attach()里,其实是将window传入,new 了一个 PhoneWindow

Activity布局流程+资源加载过程+插件化换肤思路_java_09

  1. 最后是通过callActivityOnCreate 将activity初始化并执行

Activity布局流程+资源加载过程+插件化换肤思路_java_10

PhoneWindow.java

在ActivityThread.java的performLaunchActivity方法中,是创建activity的主流程,其中建了一个Window,并将它与activity关联,而这个Window又传入了activity.attach(),new了一个PhoneWindow.java


  1. 先看setContentView(int layoutResID)
  2. setContentView里重要的就两步:①installDecor() 初始化DecorView ②mLayoutInflater.inflate(layoutResID, mContentParent)(加载XML布局)

Activity布局流程+资源加载过程+插件化换肤思路_移动开发_11

installDecor()


  1. 初始化DecorView,这里的mContentParent其实就是DecorView
  2. 将DecorView传入generateLayout()生成布局

Activity布局流程+资源加载过程+插件化换肤思路_android_12

1.1 generateDecor里就是直接return了new DecorView

Activity布局流程+资源加载过程+插件化换肤思路_android studio_13

  1. onResourcesLoaded加载资源

Activity布局流程+资源加载过程+插件化换肤思路_java_14

3.1 onResourcesLoaded()方法里,其实调用了inflater.inflate()来生成View,然后addView添加到父布局下面

Activity布局流程+资源加载过程+插件化换肤思路_java_15

mLayoutInflater.inflate() - LayoutInflater.java

  1. LayoutInflater.inflate()就是用来加载xml的

Activity布局流程+资源加载过程+插件化换肤思路_安卓_16

  1. View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)三个参数分别是 XML解析器、父布局的类型、是否要添加到父布局下面(详情看第四步)

Activity布局流程+资源加载过程+插件化换肤思路_java_17

attachToRoot 用到的地方 Activity布局流程+资源加载过程+插件化换肤思路_android_18

  1. 查看inflate方法,重点方法 createViewFromTag()创建View。

Activity布局流程+资源加载过程+插件化换肤思路_移动开发_19

3.1 查看 createViewFromTag() 方法,如果有mFactory、mFactory2、mPrivateFactory就走Factory的onCreateView,不然就走系统的onCreateView

​重点中的重点!!! 因为这里是这样构造view的,所以可以通过自定义的Factory或者Factory2,来使构造View的代码走我们自己的,这样就可以实现 -- 插件化换肤​

​还有一种方法就是直接给LayoutInflate.java这一整个类都给替换了 -- 插件化换肤​

Activity布局流程+资源加载过程+插件化换肤思路_android_20

3.2 系统的onCreateView其实是根据反射来创建的

①根据name创建constructor 构造器(之前见过的先从HashMap的缓存里取,没取到才自己创建)

②通过构造器创建View View view = constructor.newInstance(args);

③补充:因为View是通过反射constructor.newInstance(args)创建的所以这时候其实View是空的,在xml里写的各种属性都是没有的

①反射获取constructor Activity布局流程+资源加载过程+插件化换肤思路_android studio_21

② constructor.newInstance(args); 构建View Activity布局流程+资源加载过程+插件化换肤思路_android_22

③ 补充这时候xml的属性都是空的

Activity布局流程+资源加载过程+插件化换肤思路_安卓_23

  1. 因为第三步,View创建是通过反射的,所以现在xml里自己写的属性还是没有的,所以得通过获取 LayoutParams在将属性设置给View

Activity布局流程+资源加载过程+插件化换肤思路_java_24

  1. View有了(反射),属性也设置了,也添加到布局树下面了 root.addView(temp, params),所以view就构建完事了

资源加载流程

刚刚上面的全都是Activity的加载流程,下面看资源的加载流程

Resoureces的结构图

1.ResourcesManager管理着一个Resources类

2.Resources类里有他的实现类ResourcesImpl,各种创建,调用,getColor等方法都是在实现类里实现的

3.ResourcesImpl里管理着一个AssetManager

4.AssetManager负责从apk里获取资源,写入资源等 addAssetPath()

Activity布局流程+资源加载过程+插件化换肤思路_安卓_25

​resources.arsc这个文件就是apk中存资源的(字典表),addAssetPath()取的就是他的值​

Activity布局流程+资源加载过程+插件化换肤思路_移动开发_26

handleBindApplication()–ActivityThread.java

  1. 起点是ActivityThread.java handleBindApplication()方法 ,在这加载Application的

Activity布局流程+资源加载过程+插件化换肤思路_安卓_27

  1. 先new了一个Instrumentation(翻译仪表),这个类是用来加载Activity的

Activity布局流程+资源加载过程+插件化换肤思路_移动开发_28

  1. 生产了makeApplication,然后调用了Application.onCreate();

Activity布局流程+资源加载过程+插件化换肤思路_java_29

makeApplication()-- LoadedApk.java

先看Application的生产过程

  1. 先创建了上下文createAppContext

Activity布局流程+资源加载过程+插件化换肤思路_移动开发_30

  1. 通过反射ClassLoader.loadClass(className).newInstance()创建Application

Activity布局流程+资源加载过程+插件化换肤思路_android studio_31

  1. 第一步创建上下文createAppContext,点进去

​重要方法context.setResources(packageInfo.getResources()); 根据LoadedApk获取资源​

Activity布局流程+资源加载过程+插件化换肤思路_android studio_32

  1. 点进LoadedApk.getResources(),发现在ResourcesManager包里。具体里面方法是getOrCreateResources获取或者创建资源

Activity布局流程+资源加载过程+插件化换肤思路_java_33

  1. 点进getOrCreateResources方法,发现是ResourcesManager.java里的方法。他先从缓存 ​​WeakReference<ResourcesImpl>​​里取,取不到再创建资源

Activity布局流程+资源加载过程+插件化换肤思路_安卓_34

  1. 看createResourcesImpl()创建资源,是通过AssetManager创建的

Activity布局流程+资源加载过程+插件化换肤思路_java_35

  1. createAssetManager()方法里,调用了​​addApkAssets()重点​​​方法,这个方法是native方法,作用是给一个路径,用来加载apk里的资源​​在android27 里 叫addAssetPath()​

Activity布局流程+资源加载过程+插件化换肤思路_移动开发_36

插件化换肤思路

根据上面最后第7步:

Activity布局流程+资源加载过程+插件化换肤思路_android studio_37

1.apk里所有的资源都是通过/resources.arsc 这个表格,然后去找具体apk的资源的。 Activity布局流程+资源加载过程+插件化换肤思路_android_38

2.而Resoures实际是通过AssetManager来资源加载的,外面的都是一层包装 Activity布局流程+资源加载过程+插件化换肤思路_android studio_39

3.AssetManager重点方法根据资源id找包名、类型、资源等等。根据name获取资源

Activity布局流程+资源加载过程+插件化换肤思路_java_40

插件化换肤思路:

1.插件apk跟宿主apk有同名的资源

2.取宿主apk的资源名,去插件apk里找

3.将插件apk的值替换掉宿主apk的值 Activity布局流程+资源加载过程+插件化换肤思路_移动开发_41

具体代码 Activity布局流程+资源加载过程+插件化换肤思路_java_42

完整的思路:

1.收集xml数据,根据View创建过程的Factory2(源码里拷贝过来就行)需要修改的地方就是View创建完事以后,将需要修改的属性及他的View记录下来(比如要改color、src、backgrand)

2.记录的类型大概这样,​​所有要换的属性->List<View> -> List<View中要换的属性>​

Activity布局流程+资源加载过程+插件化换肤思路_android studio_43

3.读取皮肤包里的内容。

先通过assets.addAssetPath()加载进来,这样就能通过assetManager来获取皮肤包里的资源了

4.如果遇到了需要替换的属性(color、src、backgrand等)那就替换,通过assetManager里的方法

Activity布局流程+资源加载过程+插件化换肤思路_移动开发_44

具体代码: Activity布局流程+资源加载过程+插件化换肤思路_android studio_45

4具体设置,需要改的view的属性,替换成皮肤包的里的id

Activity布局流程+资源加载过程+插件化换肤思路_android_46

最后

小编在网上收集了一些 Android 开发相关的学习文档、面试题、Android 核心笔记等等文档,希望能帮助到大家学习提升,如有需要参考的可以直接去访问查阅。

Activity布局流程+资源加载过程+插件化换肤思路_移动开发_47



举报

相关推荐

0 条评论