原理
Xml 解析过程
类图
时序图
读取 Resource 资源过程
类图
活动图
换肤思路
给 LayoutInflater 设置自定义的 SkinLayoutInflaterFactory,实现 LayoutInflater.Factory2,用来记录创建 View 的属性和 resId,后续可以设置记录 View 的属性。
使用观察者模式,各个 Activity 为被观察者,Factory2 为观察者,订阅 Activity 的消息。当触发 loadSkin 后,调用 setChanged()、notifyObservers(),发送消息。
步骤
(细化一下)
-
收集 xml view 数据
如何去收集XML信息
- 利用View的实例化流程
- 自定义SkinLayoutInflaterFactory
-
统计需要换肤的属性
统计需要换肤的属性
SkinAttribute
记录需要的属性SkinPair
记录一个属性 属性名字--对应的资源idSkinView
一个view对应多个属性View--List<SkinPair>
- SkinAttribute 一个xml对应多个view
List<SkinView>
public void look(View view, AttributeSet attrs)
记录下view对应的属性
public void applySkin()
修改属性(属性的值应该来自于皮肤包) -
制作皮肤包 apk
生成一个无代码的APK文件即可
-
读取皮肤包
SkinManager中public void loadSkin(String skinPath)
读取资源包信息 -
执行换肤
SkinManager 通知 SkinLayoutInflaterFactory 更新UI
优点
- 用户体验好,无闪烁
- 拓展和维护方便,入侵性小,低耦合
- 插件化开发,任何 app 都是皮肤包
- 即时生效,无需重启 app
反射注意点
-
版本适配
-
绕开 UnsupportedAppUsage 注解的限制
参考项目的
ReflectionUtil
完整代码参考