RecyclerView子View不刷新(RequestLayout无效),RecyclerView.mEatRequestLayout

问题:

最近项目中发现,有时候recyclerView刷新了数据后,部分ItemView里的文字出现被截断的问题,或者是如果textView支持过长打点的话,出现提前打点,也就是文字长度还未超出限定范围就开始打点了。

问题分析:

android中,View的内容如果发生改变,导致内容超出当前View的宽高范围,需要重新请求视图树进行测量和布局,也就是调用requestLayout。如TextView的setText方法,ImageView的setImageResource,View的setLayoutParams方法。

问题原因可能是textView的setText方法未引起视图树的重新测量和布局,尝试在setText后,手动调用textView的requestLayout方法,请求刷新视图树。但是某些情况下,特别是首次刷新数据时候,还是会出现文字被剪断问题。

考虑是否是textView向上请求requestLayout被某一个ViewGroup给拦截了。

先分析view的requestLayout是如何传递给RootViewImpl的。

view调用requestLayout之后,会调用parent布局的requestLayout,parent布局又会再调用其parent布局的requestLayout,递归直到ViewRootImpl,并把沿途经过的所有View都标记上PFLAG_FORCE_LAYOUT、PFLAG_INVALIDATED这两个Flag,那么在下一次VSync(16ms一次)到来的时候,将会重新计算和布局所有标记了PFLAG_FORCE_LAYOUT的View,也就是onMeasure和onLayout方法将被调用,接着draw所有标记了PFLAG_INVALIDATED的View,也就是draw方法将被调用。

我重写了textView的onLayout方法,发现,requestLayout后,textView的onLayout并没有执行。

也就是说ViewRootImpl并没有收到textView的requestLayout请求,所以说,是被某一个ViewGroup给拦截了。

之后,使用排除法,从视图树的顶部往下走,挨个调用requestLayout,看看它的onLayout方法是否执行,当尝试到内部的那个recyclerView的时候,发现,其requestLayout也失效了,也就是说外层的RecyclerView消费了所有孩子View的requestLayout请求。

查看RecyclerView的requestLayout方法源码:

public void requestLayout() {
    if(!this.mEatRequestLayout) {
        super.requestLayout();
    } else {
        this.mLayoutRequestEaten = true;
    }
}

如果变量mEatRequestLayout为true的话,拦截requestLayout的向上传递。

如此一来,只要重写外层recyclerView的requestLayout方法,在调用super.requestLayout方法之前,使用反射将mEatRequestLayout设置成false即可。

是否导致其他问题:

目前来看,没出现其他问题。但是性能上可能会有一些问题,RecyclerView之所以要消费requestLayout请求,一定有其原因,具体还未进行分析。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值