razerdp / BasePopup

Android下打造通用便捷的PopupWindow弹窗库
https://github.com/razerdp/BasePopup
Apache License 2.0
5.2k stars 759 forks source link

【再次出现】在oncreate调用showPopupWindow后立马调用dismiss,会导致弹窗不消失【再次出现】 #474

Closed SelectSex closed 1 year ago

SelectSex commented 2 years ago

系统版本:Android 9 库版本:3.2.1-snap

此bug依然存在,发现是改版优化了下图的代码 tryToShowPopup方法 image 导致用户第一次调用show后立即dismiss,会因为窗口未准备妥当,所以将show任务延后执行了,但是dismiss并没有延后执行,所以此次dismiss是无效执行,然后延后执行的show任务执行成功,导致弹窗依旧存在,

我这边是这样解决的

init {
      contentView = bindView.root
      bindView.root.isInvisible = true
      setBackgroundColor(0)
      showPopupWindow()
      setOnPopupWindowShowListener {
          dismiss()
          setOnPopupWindowShowListener(null)
      }
  }

有些人好奇我为什么这样操作,看起来好骚呀,也很无用

我解释下,我的有个业务,列表中多个item,每个点击后都是弹出同一个弹窗【我把弹出复用了】,

但是第一个点击后,因为弹窗加载耗时不少时间,此时用户等待弹窗弹出的过程中是可以继续点击其他item的,因为业务特殊,记录的点击的一个item和用户等待时候点击的其他item会混乱,

所以我想了一天还是觉的应该 预加载 弹窗,

怎么做当然是再oncreate中show一下然后立马dismiss,并且show的时候将rootview设置为gone,等下次show的时候会主动将rootview 显示出来,

等用户点击的时候已经是预加载过的弹窗,点一下立马弹出,这下用户就没法点击其余的item

SelectSex commented 2 years ago

同时还发现只要设置了动画,则 哪怕我设置了 bindView.root.isInvisible = true ,也会显示view,就很无奈了

SelectSex commented 2 years ago

动画设置,改成了再init中动态设置,而不是重写 onCreateShowAnimation 方法来设置动画

razerdp commented 2 years ago

确实是个神奇的需求……不过show之后立马dismiss也确实需要考虑,后续我弄一下。(总算有个更新动力了)

SelectSex commented 2 years ago

确实是个神奇的需求……不过show之后立马dismiss也确实需要考虑,后续我弄一下。(总算有个更新动力了)

神奇的是,我这边现在的方案在init中直接设置show成功的监听来执行dismiss,因为我有个弹窗使用了dismiss(false)传参, 然后我就发现神奇地方了,

会崩溃,仔细看了源码,是show成功监听中是不能立即调用dismiss的如果调用也是默认走的dismiss(true),表示真正的dismiss是延时处理的,如果传false表示立即执行dismiss,会在“razerdp.basepopup.PopupDecorViewProxy#onApplyWindowInsets”中因为mHelper先被重置为null而空指针异常。

此时我又有了骚操作,在 BaseActivityoncreate预加载了一个 LoadingPopWindow

又有了新的发现,我的首页activity,多个item都可以跳转不同的新activity,每个新activity打开都会预加载当前activity的LoadingPopWindow,我发现了10个新页面有5个新页面在预加载完成LoadingPopWindow然后再LoadingPopWindowdismiss的时候,发生了activity视觉透明看到下面的老activity闪动效果

经排查我试着自己设置延时500ms执行dismiss,可以消除这个现象。这就尴尬了,300ms还不影响使用,500ms就已经有点影响效果,用户打开新页面快速返回或者点击新页面的内容,会因为透明的预加载 LoadingPopWindow未dismiss而被拦截掉点击事件。

所以现在,我还是将预加载不影响使用的实现方案交给可爱的作者大佬来解决了,辛苦了,大佬

SelectSex commented 2 years ago

对了,经排查我试着自己设置延时500ms执行dismiss,可以消除这个现象 随着减少这个500ms为400,300,200,那么发生视觉透明的闪动效果的出现次数越高。

razerdp commented 2 years ago

手机目前拿去修了,等修好后我回来看看

ChawLoo commented 2 years ago

其实这个场景很多,我调用接口,flow的onStart中加了显示弹窗,然后onCompletion中隐藏弹窗,正常网络请求没问题,毕竟自带延时(除非网络真的特别好,秒回),但是我自己又写了缓存,读取的是本地数据库正常情况都是立即返回的,这个时候就会遇到无法dimiss的问题了。本来准备提这个问题,发现已经有了,就来评(cui)论(geng)一下

razerdp commented 2 years ago

近期终于有空,明天开始我继续迭代项目,优先看看你这个问题哈~

huwencheng commented 2 years ago

我也遇到了这个问题,show之后马上dismiss会概率性渗透看到底部的页面,体验不好,也来评(cui)论(geng)一下

razerdp commented 2 years ago

ya,今晚我找了下原因,一楼定位是对的。

start showing标记位在prepareshow中设置,但是因为宿主没准备好因此退出了,进而导致dismiss的时候判断isshowing为false,因此不执行dismiss。

目前思考着要不按照时序把show和dismiss都怼入handler中,这样某个准备好就执行下一个。。。(缺点是不排除泄露的可能,当然也许可以利用宿主的handler)

微信截图_20220922004210

razerdp commented 2 years ago

这个问题目前来说基本都是因为宿主未完成windowToken的创建而导致延迟show的情况,在延迟期间需要dismiss

隐刺有两种修复方向。。。

  1. 直接cancel本次show,表现上就是弹窗根本没有出现过
  2. 等待弹窗出现后再直行dismiss.
razerdp commented 2 years ago

这个问题目前来说基本都是因为宿主未完成windowToken的创建而导致延迟show的情况,在延迟期间需要dismiss

隐刺有两种修复方向。。。

  1. 直接cancel本次show,表现上就是弹窗根本没有出现过
  2. 等待弹窗出现后再直行dismiss.

最终决定,我两种都支持,默认方式1,就是如果没展示而又需要dismiss,则打断本次展示~

后续提交到dev分支进行测试

razerdp commented 1 year ago

fixed in 3.2.1