activity调用fragment的方法_从inflate方法开始,搞懂LayoutInflater的inflate过程(上)

从inflate方法开始,搞懂LayoutInflater的inflate过程(上)

本来是完整一份的,结果一页写不下,分页,感觉知乎显示效果不行,来,点我博客查看
本文主要介绍:LayoutInflater
本文适合对象:打算搞懂LayoutInflater的inflate的开发者
本文字数:约2.5万,阅读时间:约2H

问题

先从表象入手

在Android开发过程中,很多地方都不可避免的使用到inflate方法,如在使用RecycleView的时候构建ViewHolder对象,给Fragment进行CreateView

我们通常是inflater.inflate(R.layout.xxx, container, false)或者LayoutInflater.from(parent.context).inflate(R.layout.xxx, parent, false)来调用inflate方法的,不难发现,inflate方法的作用是将一个 xml 布局文件变成一个 view 对象。然而仅仅是根据模板,按照固定的"规律"去修改某些参数来实现目标,只能叫做是「使用」而已

那么,我们就来将它「分解」成明确的「问题」,来具体的「学习」吧

  1. LayoutInflaterinflater 这些语句的「头部」是什么?怎么来的?
  2. inflate 方法的「参数」是什么意思,有什么用?
  3. 这些语句是怎么实现转换 xmlview 的?
  4. 我除了常见的用法还能怎么用它

Question One:「头部」

官方文档

思考的First Step,问其所来

官方文档对LayoutInflater的说明如下:

v2-bd73f7fcef990c6f7f1671c0a7f19712_b.jpg

简单的翻译过来就是:

  1. 这玩意是用来将 xml 转换为 view
  2. 这玩意不能直接new初始化,通过ActivitySystemService获取,你也可以自定义他的工厂方法
  3. 因为性能问题,他只能把写在layout里被预处理过的 xml 转换为 view ,不能随便找个xml文件就让他转换

回归表象

那好了,第一个问题解决了,LayoutInflater是一个不能直接new的类,他来管 xml 转换为 view ,我们在adapter里通过LayoutInflater.from(context)获取实例,fragment则是直接使用了FragmentManager调用Fragment.onCreateView的时候传过来的inflater对象

Question Two:「方法」

inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) 方法有三个参数,第一个参数很好理解,就是前文所说的, xml 转换为 viewlayout xml 对应的资源ID。第二第三个参数又什么意思呢?我转换成View为什么需要它呢?

官方文档

v2-1d09aa34e58dfd689a8c724df6b87df0_b.jpg

简单翻译:

  1. root是要转换的 xml 将要存在的外部ViewGroup
  2. xml 转换成 view 后要不要 addViewroot ( ViewGroup )

这是个啥意思呢,看了之后似懂非懂,我还是一脸懵逼。

测试

纸上学来终觉浅,只是看文档还是不行,不如自己上手试试,把自己脑子里的可能性都弄出来试试看效果,跑出来啥样就是啥样了。

按排列组合来说,我们一共有四种(如果你想到更多可能性,不妨自己写出来跑跑看)

  1. root = null, attachToRoot = false
  2. root = null, attachToRoot = true
  3. root = viewgroup, attachToRoot = false
  4. root = viewgroup, attachToRoot = true

接下来我们一个个实验,实验的过程为,通过activitygetLayoutInflater()方法获取inflater对象,调用其inflate方法,传递不同的参数,将得到的view添加到activity布局的viewgroup中,查看结果。

首先是布局展示,activity的布局只有一个蓝底的ViewGroup,而要加载的view也只是一个黄色的View

v2-44fd627f0dd6768cd3c8f805b0a3ab68_b.jpg

v2-9f0c18253c08446f07f31e4227254a98_b.jpg

注意我给蓝底加了一句android:paddingTop="32dp",黄底加了一句android:layout_margin="4dp"

测试①

v2-c5a245585173a462e9af2058a4f077fc_b.jpg

我们看到黄色的view几乎填满了整个activityviewwidthheightmargin都无效,但是viewgrouppadding是有效的。

但是我们还不能确定是root = nullattachToRoot = false中哪个的原因,我们继续测试

测试②

v2-90f6ad9e2bd6177742846109a6cef94e_b.jpg

我们可以看到黄色的view里面设置的width height margin还是无效的,但是viewgrouppadding是有效的。

通过这两个测试,我猜测root的效果是控制 xml 里关于layoutparam的设置是否有效,但是不是这样还要看接下来的测试。而viewgroup的padding参数是不受影响的,这个也好理解,因为是ViewGroup的属性,在onDraw方法里处理的。

测试③

v2-d35562fc44c52d121f4412ea5b5066bd_b.jpg

我们可以看到黄色的view里面设置的width height margin也都有效了

也就是说,root的猜测基本是坐实了,接下来就剩attachToRoot还是一头雾水了

测试④

v2-75df2699b16c60d12df30c06012d5026_b.jpg

Crash!出问题了,看看报错信息:

The specified child already has a parent. You must call removeView() on the child's parent first.

这娃儿已经有个爹了,你要当他爹得先让他现在的爹 removeView()

啥意思,已经有个爹了?这爹是谁,他转换的过程也就接触到一个viewgroup啊,难道说attachToRoot = true的话就直接addView()了?试试看

测试⑤

v2-6af1d0e963756dda6a38c0cf79c877a5_b.jpg

果然和我们想的一样……那么,可以总结一下了

总结

  1. root参数将决定viewlayoutparam,如果为null,那xml里定义的最外层viewlayoutparam将全部无效
  2. attachToRoot表示是否需要一键addView(),如果root为null,那这个参数将被自动忽略
下篇
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值