UI布局层次分析与插件化换肤思路

幻昼 2021年11月11日 1,017次浏览

原理

Xml 解析过程

类图

Xml 解析过程类图

时序图

Xml 解析过程时序图

读取 Resource 资源过程

类图

Res 资源加载类图

活动图

Res 资源加载活动图

换肤思路

给 LayoutInflater 设置自定义的 SkinLayoutInflaterFactory,实现 LayoutInflater.Factory2,用来记录创建 View 的属性和 resId,后续可以设置记录 View 的属性。

使用观察者模式,各个 Activity 为被观察者,Factory2 为观察者,订阅 Activity 的消息。当触发 loadSkin 后,调用 setChanged()、notifyObservers(),发送消息。

步骤

(细化一下)

  1. 收集 xml view 数据

    如何去收集XML信息

    • 利用View的实例化流程
    • 自定义SkinLayoutInflaterFactory
  2. 统计需要换肤的属性

    统计需要换肤的属性

    SkinAttribute记录需要的属性

    • SkinPair 记录一个属性 属性名字--对应的资源id
    • SkinView 一个view对应多个属性 View--List<SkinPair>
    • SkinAttribute 一个xml对应多个view List<SkinView>
    • public void look(View view, AttributeSet attrs) 记录下view对应的属性

    public void applySkin() 修改属性(属性的值应该来自于皮肤包)

  3. 制作皮肤包 apk

    生成一个无代码的APK文件即可

  4. 读取皮肤包

    SkinManager中public void loadSkin(String skinPath) 读取资源包信息

  5. 执行换肤

    SkinManager 通知 SkinLayoutInflaterFactory 更新UI

优点

  1. 用户体验好,无闪烁
  2. 拓展和维护方便,入侵性小,低耦合
  3. 插件化开发,任何 app 都是皮肤包
  4. 即时生效,无需重启 app

反射注意点

  1. 版本适配

  2. 绕开 UnsupportedAppUsage 注解的限制

    参考项目的 ReflectionUtil

完整代码参考

https://gitlab.xlxs.top/xlxsui/jinskin