Android视图加载优化——Factory2设置方法_android viewfactory

三、如何兼容 AppCompatActivity 的 Factory2

如何既能使用自己的 Factory2,又能让 AppCompatActivity 保留自己的 Facotory 呢?下面给出几种解决方法。

(一)代理给 AppCompatDelegate

AppCompatDelegate 内部有一个 createView 方法,不要和 FactoryFactory2onCreateView 混淆。

我们仅仅只需要修改 setFactory2 ,将不需要处理的情况代理给 AppCompatDelegate

运行一下,TextView 变成了 RedTextViewButton 变成了 AppCompatButton ,成功!

(二)重写 viewInflaterClass

我们看一下 AppCompatDelegatecreateView 方法,当 AppCompatViewInflater 没有初始化时,会通过反射创建。要初始化的类由 R.styleable.AppCompatTheme_viewInflaterClass 指定,默认就是 AppCompatViewInflater

FactoryActivity 的 theme 进行如下修改:

就可以让 AppCompatDelegate 使用我们自定义的 AppCompatViewInflater 的子类 CustomViewInflater :

Google 的 Material Design Components 实际上就是使用这种方法来将 Button 修改为对应的 MaterialButton ,在 这里 可以看到 。

这个方法很强大,它可以让你的 App 使用 Material Design Components 这样的类库,却仅仅只需要设置合适的主题。

注意 AppCompatViewInflater 还提供了一个可以被重写的 createView() 方法,用来处理默认情况下没有被处理的新的组件。当 AppCompatViewInflater 没有处理特定的组件类型,就可以使用这个方法。

(三)自定义 LayoutInflater

第三种方法是重写 ActivityattachBaseContext ,改写 ContextThemeWrappergetSystemService 方法,返回自定义的 LayoutInflater 。自定义的 LayoutInflater 可以重写 setFactory2 方法,加入自己的处理逻辑。这个方法是我从 ViewPump 学到的。

四、一些小细节

下面介绍了 AppCompatDelegate 在进行视图加载过程中的几个小细节。

(一)onCreateView

我们希望 Factory2onCreateView 方法直接调用 createView (代理给 AppCompatDelegate 那一小节中提到过) 。事实上,的确也是这么做的。但是代码中还多了一点东西 - 调用了 callActivityOnCreateView 。在 AppCompatDelegateImplV14 中是这样的:

看一下 LayoutInflater源码 , createViewFromTag 尝试通过 factory 获取 view 。如果没有获取到,会使用 mPrivateFactory 。如果依旧没有获取到,会通过视图标签去创建 view 。mPrivateFactory 是在 Activity 中设置的。

有意思的是, mPrivateFactory 的作用是解析 fragment 标签。

在 API 14 之前,LayoutInflater 并没有提供 mPrivateFactory 让 Activity 可以有个兜底方案来创建 View 。因此,callActivityOnCreateView 在低版本中提供了这一功能。但这现在都没有关系了,反正 AppCompat 目前只兼容 Api 14+ 。

另一个有意思的知识点是 Window.CallbackWindow.Callback 是一个回调,让调用者可以拦截 key 的分发,面板,菜单等等。它让 AppCompatActivity 可以处理一些特定时间,例如菜单键,返回键等。

(二)createView

总的来说,AppCompatDelegateImplV9 做了两件事。首先,创建了 AppCompatViewInflater 或者在 theme 中指定的其他子类。第二,通过 inflater 创建 View 。

AppCompatViewInflatercreateView 使用了正确的 Context (考虑到支持 app:themeandroid:theme,需要对 Context 进行包装),根据组件名称创建对应的 AppCompat 组件(例如,如果是 TextView,就调用 createTextView 方法返回 AppCompatTextView)。

(三)支持 app:theme

从 Android 5.0 开始,可以给 View 设置 app:theme 以覆盖特定 View 及其子类的属性。AppCompat 通过继承父 View 的 context 在 Android 5.0 之前复制这一行为。

在 AppCompat 加载 View 之前,它先拿到父 View 的 Context,然后尝试创建一个 ContextThemeWrapper(android:theme 或者 app:theme),保证使用正确的 context 来加载组件。

另外,如果开发者明确声明需要在资源中使用矢量图,AppCompat 在 Android 5.0 之前还提供了 TintContextWrapper 来包装 Context 。

(四)View 的创建和兜底

通过这些信息,系统已经准备好如何创建 View 了。

遍历支持的组件列表,对于通用的 View,如 TextView, ImageView ,直接生成对应的 AppCompat 子类。如果是未知类型的 View,将使用正确的 Context 调用 createView,默认返回 null,但一般会被 AppCompatViewInflater 的子类重写。

如果这时候 view 仍然是 null,会检查 view 的原始 context 是否和父 View 的 context 一致。这种情况会发生在子 View 的 android:theme 和 父 View 不一致。

在检查 android:onClick 之后,view 就被返回了。

五、总结和使用实例

总结一下,AppCompatActivity 通过给 LayoutInflater 设置 Factory2 来介入 View 的创建过程,以提供向后兼容性(为组件提供 tint,处理 android:theme 等)。它也保证了可扩展性,开发者可以进行一些定制处理。

除了 Appcompat,这一技巧被用来完成了更多有意思的事情。Probe (现已废弃) 提供了 OvermeasureInterceptor 来记录 View 的测量次数,LayoutBoundsInterceptor 来高亮 View 的边界。

Calligraphy 使用这一技巧方便的为 TextView 添加字体。它使用了ViewPump 库,在 wiki 中提供了一些可能的使用方式。

最后,Google 的 Material Components for Android 通过自定义 AppCompatViewInflaterButton 替换为 MaterialButton

原文作者:ahmed el-helw

原文链接:AppCompat View Inflation

全套视频资料:

一、面试合集

二、源码解析合集

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

image

七大模块学习资料:如NDK模块开发、Android框架体系架构…

image

2021大厂面试真题:

image

只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

到真正的技术提升。**

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 11
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值