Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

修复4.3.3中AndroidPAG在recyclerview使用导致隐藏被显示问题 #1710

Merged
merged 6 commits into from
Sep 21, 2023

Conversation

fanmingyi
Copy link
Contributor

@fanmingyi fanmingyi commented Sep 5, 2023

问题描述

在4.3.3版本中recyclerview使用时会有一些情况导致被隐藏的PAG在onResume被强制设置可见,这在业务上是不可接受。
问题视频如下:
https://github.com/Tencent/libpag/assets/22413240/e9f6ac9f-a626-4197-a385-75993e6a958d
另外附上最小化复现Demo:
Demo链接

问题原因

在大多数情况调用View#setVisibility会触发View#onVisibilityAggregated但是在recyclerview情况不一定符合PAG开发者的预期。
PAGView#onVisibilityAggregated做了一些可见性判断处理。
RecyclerView.Adapter#onBindViewHolder回调时item根视图没有附加到RecyclerView之上。
View#setVisibility时会触发View#setFlags回调,并在setFlags函数间接回调到View#onVisibilityAggregated

  //View.java
  void setFlags(int flags, int mask) {
  
      if (mParent != null && getWindowVisibility() == VISIBLE &&
                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
                    //最终回调到onVisibilityAggregated
                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
                }
 }

在继续往下追溯源码的就是((ViewGroup) mParent).isShown())相关问题,这里就是由于RecyclerView没有绑定item视图问题(isShown会不断向上找父view,但是此时父View没有)。

修复方式

在调用View#setVisibility时判断是否需要手动调用Pag的checkVisible函数。

//PAGView.java
 @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        //When calling the setVisibility function,
        //it does not necessarily trigger a callback to the onVisibilityAggregated method.
        //Therefore, it is necessary to handle this specific situation on your own.
        ViewParent mParent = getParent();
        if (mParent != null && getWindowVisibility() == VISIBLE &&
                ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
        }else {
            checkVisible();
        }
    }

注:这里之所以把View中所有if条件判定直接搬迁过来不做逻辑裁剪是为了可读性和维护成本(未来源码改动也只是复制粘贴),且编译器会自动消除else分支。

…trigger a callback to the onVisibilityAggregated method.Therefore, it is necessary to handle this specific situation on your own.
@lvpengwei lvpengwei merged commit 8626589 into Tencent:main Sep 21, 2023
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants