Closed Jove-zhou closed 1 year ago
1 还在找 从源码分析 某个下拉刷新完成并且没有更多数据的场景下 mState一直是Refreshing且未走到2985 而一直执行2994 最后导致溢出 2 不是必现 从用户量维度万分之一
我已经Fork
SmartRefrashLayout仓库并且合并他的PR来避免产生此问题, 不过具体更新得等我有空再进行
但是此问题我无法复现会导致比较麻烦
好的 感谢
如果你能发起pr修复就更好了,毕竟我无法复现此问题不太确定
我在尝试复现修复,目前有点眉目,等待下次发版后看反馈结果
在 2023-04-17 15:24:35,"劉強東" @.***> 写道:
如果你能发起pr修复就更好了,毕竟我无法复现此问题不太确定
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>
@Jove-zhou 问题有进展吗?
还未解决
发件人: @. @.> 代表 | @.> 日期: 星期六, 2023年5月27日 00:35 收件人: liangjingkanji/BRV @.> 抄送: Jove-zhou @.>, Mention @.> 主题: Re: [liangjingkanji/BRV] 集成的SmartRefreshLayout在完成刷新的判断中存在循环调用会导致堆栈溢出 (Issue #353)
@Jove-zhouhttps://github.com/Jove-zhou 问题有进展吗?
― Reply to this email directly, view it on GitHubhttps://github.com/liangjingkanji/BRV/issues/353#issuecomment-1564646380, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AA7GK5CAE5E5XW7IJGUOFZDXIDLU5ANCNFSM6AAAAAAWYQHBRU. You are receiving this because you were mentioned.Message ID: @.***>
这个问题我遇到过,我的情况是这样的:
这个可能是库的问题,没有阻止两次 refresh 的刷新并且会陷入循环调用。但是我遇到的这个问题应该是可以人为避免的,你可以检查一下你的代码是否是我这种情况
这个问题我遇到过,我的情况是这样的:
- 在 onRefresh 触发网络请求后,还未刷新数据时,此时 state 为 RefreshState.Refreshing
- 因为某种原因再次触发刷新方法 ,比如 autoRefresh、refresh、refreshing 等。因为之前的 state 已经是 RefreshState.Refreshing 了,这个时候,当步骤 1 的网络请求回来后,调用 addData 刷新,就会陷入问题所说的循环调用
这个可能是库的问题,没有阻止两次 refresh 的刷新并且会陷入循环调用。但是我遇到的这个问题应该是可以人为避免的,你可以检查一下你的代码是否是我这种情况
并非你所说的这种情况 目前来看 非Refreshing的状态下完成一样会有此问题: at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:468) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData (SmartRefreshLayout.java:3239) com.drake.brv.PageRefreshLayout.finish (PageRefreshLayout.kt:431) com.drake.brv.PageRefreshLayout.addData (PageRefreshLayout.kt:323) com.drake.brv.PageRefreshLayout.addData$default (PageRefreshLayout.kt:279)
无法复现此问题, 但是遇到过发生问题的人但没有去解决
} else if (mState == RefreshState.Loading && mRefreshFooter != null && mRefreshContent != null) {
count++;
mHandler.postDelayed(this, more);
//提前设置 状态为 LoadFinish 防止 postDelayed 导致 finishLoadMore 过后,外部判断 state 还是 Loading
notifyStateChanged(RefreshState.LoadFinish);
return;
}
但是没有进入这条件估计是mRefreshFooter
或mRefreshContent
为null
不仅如此 还会走到延迟为0的情况 已尝试多种方式 仍无法避免
Non-fatal Exception: java.lang.StackOverflowError: stack size 8188KB at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:476) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:476) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:476) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:476) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:476) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:476) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:476) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:476) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:476) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:476) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.drake.brv.PageRefreshLayout.finish(PageRefreshLayout.kt:439) at com.drake.brv.PageRefreshLayout.addData(PageRefreshLayout.kt:331) at com.drake.brv.PageRefreshLayout.addData$default(PageRefreshLayout.kt:287)
让我能复现此问题我就能修复
是否初始化?
SmartRefreshLayout.setDefaultRefreshHeaderCreator { context, layout -> MaterialHeader(this) }
SmartRefreshLayout.setDefaultRefreshFooterCreator { context, layout -> ClassicsFooter(this) }
@Jove-zhou
同样遇到这个问题了... @liangjingkanji 有眉目了嘛
同样遇到这个问题了... @liangjingkanji 有眉目了嘛
这属于SmartRefreshLayout的bug, 我无法复现此问题所以无法修复
如果能让我复现此问题或者可以尝试反馈给SmartRefreshLayout作者
Duplicate of scwang90/SmartRefreshLayout#1470 应该和他问题相同, 但是我不清楚他这个Fragment返回是什么操作, 你们谁能复现
可能是你们在Fragment的View还未创建时就开始调用加载
这问题我研究出来了,但这个问题是SmartRefreshLayout的问题,跟BRV没有关系
Activity的 onCreate
中,对 RecyclerVIew
赋值
val data = mutableListOf<Any>().apply {
for (i in 0..9) {
when (i) {
1, 2 -> add(FullSpanModel())
else -> add(SimpleModel())
}
}
}
binding.refresh.addData(data) { false }
因为没有更多数据了,会调用 SmartRefreshLayout.finishRefreshWithNoMoreData()
,而该方法最终会调用finishRefresh()
,关键点在这里:
判断条件中 mRefreshHeader
为null导致没有进入方法更改状态,正常应该修改为RefreshFinish,从而导致最后调用setNoMoreData方法里面
@Override
public RefreshLayout setNoMoreData(boolean noMoreData) {
if (mState == RefreshState.Refreshing && noMoreData) {
// !!!!看这里 判断mState仍然处于Refreshing 且 noMoreData =true 至此进入递归循环调用
finishRefreshWithNoMoreData();
} else if (mState == RefreshState.Loading && noMoreData) {
finishLoadMoreWithNoMoreData();
} else if (mFooterNoMoreData != noMoreData) {
//不重要
}
return this;
}
为什么前面判断的 mRefreshHeader
为null 呢,查看了一下源码,发现初始化的起点在
问题点就在这里,自定义View的onAttachedToWindow 生命周期是这样的:
Act.onCreate -> Act.onResume -> Act.onAttachedToWindow -> View.onAttachedToWindow
所以一旦立马调用 finishRefreshWithNoMoreData 就会出现堆栈溢出的递归问题。
demo没问题是因为demo的列表都是在Fragment的onViewCreated 生命周期里面执行的,没有该问题,
我fork了,创建了一个TestAct,必现了
https://github.com/ChawLoo/BRV
大佬分析的很仔细, 有没比较好的解决方案 @ChawLoo
我通过拦截PageRefreshLayout.setNoMoreData
来避免循环调用
private var currentNoMoreData: Boolean? = null
override fun setNoMoreData(noMoreData: Boolean): RefreshLayout {
if (mAttachedToWindow) {
super.setNoMoreData(noMoreData)
} else {
if (currentNoMoreData != noMoreData) {
currentNoMoreData = noMoreData
super.setNoMoreData(noMoreData)
}
}
return this
}
请升级至最新版本
在网络请求或异步任务快于Activity渲染就会导致此问题, 的确发生概率非常小
并且由于demo都在Fragment中的确无法复现此问题
已更新为最新版 从线上看 并不是 此原因造成的
Non-fatal Exception: java.lang.StackOverflowError: stack size 8188KB at com.drake.brv.PageRefreshLayout.setNoMoreData(PageRefreshLayout.kt:472) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:491) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2857) at com.drake.brv.PageRefreshLayout.setNoMoreData(PageRefreshLayout.kt:472) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:491)
试下1.5.1
版本, 我再次尝试修复 @Jove-zhou
implementation 'com.github.liangjingkanji:BRV:1.5.1'
@Jove-zhou 该旧版本1.5.1一律禁止重复调用, 你试下这个版本
好的
@Jove-zhou 该旧版本1.5.1一律禁止重复调用, 你试下这个版本
到现在为止 没有再出现了
不知道为什么mAttachedToWindow
判断竟然还无效
@Jove-zhou 该旧版本1.5.1一律禁止重复调用, 你试下这个版本
到现在为止 没有再出现了
你能再换成1.5.2
版本试下是否又会出现循环调用吗, 因为无法复现此问题, 所以我并不能确认改成1.5.1
方案
1.5.2 之前用过 有问题
问题描述
SmartRefreshLayout现有版本存在某些特定情景导致刷新完成判断循环调用 此问题由来已久 没有完全解决
期望行为
能否集成一个轻量级刷新和自动加载三方库,或者仅提供自动加载回调
如何复现
截图
Non-fatal Exception: java.lang.StackOverflowError: stack size 8188KB at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$6.run(SmartRefreshLayout.java:2994) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefresh(SmartRefreshLayout.java:3043) at com.drake.brv.PageRefreshLayout.finishRefresh(PageRefreshLayout.kt:457) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefreshWithNoMoreData(SmartRefreshLayout.java:3056) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$6.run(SmartRefreshLayout.java:2994) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefresh(SmartRefreshLayout.java:3043) at com.drake.brv.PageRefreshLayout.finishRefresh(PageRefreshLayout.kt:457) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefreshWithNoMoreData(SmartRefreshLayout.java:3056) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$6.run(SmartRefreshLayout.java:2994) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefresh(SmartRefreshLayout.java:3043) at com.drake.brv.PageRefreshLayout.finishRefresh(PageRefreshLayout.kt:457) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefreshWithNoMoreData(SmartRefreshLayout.java:3056) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$6.run(SmartRefreshLayout.java:2994) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefresh(SmartRefreshLayout.java:3043) at com.drake.brv.PageRefreshLayout.finishRefresh(PageRefreshLayout.kt:457) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefreshWithNoMoreData(SmartRefreshLayout.java:3056) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$6.run(SmartRefreshLayout.java:2994) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefresh(SmartRefreshLayout.java:3043) at com.drake.brv.PageRefreshLayout.finishRefresh(PageRefreshLayout.kt:457) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefreshWithNoMoreData(SmartRefreshLayout.java:3056) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$6.run(SmartRefreshLayout.java:2994) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefresh(SmartRefreshLayout.java:3043) at com.drake.brv.PageRefreshLayout.finishRefresh(PageRefreshLayout.kt:457) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefreshWithNoMoreData(SmartRefreshLayout.java:3056) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$6.run(SmartRefreshLayout.java:2994) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefresh(SmartRefreshLayout.java:3043) at com.drake.brv.PageRefreshLayout.finishRefresh(PageRefreshLayout.kt:457) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefreshWithNoMoreData(SmartRefreshLayout.java:3056) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$6.run(SmartRefreshLayout.java:2994) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefresh(SmartRefreshLayout.java:3043) at com.drake.brv.PageRefreshLayout.finishRefresh(PageRefreshLayout.kt:457) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefreshWithNoMoreData(SmartRefreshLayout.java:3056) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$6.run(SmartRefreshLayout.java:2994) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefresh(SmartRefreshLayout.java:3043) at com.drake.brv.PageRefreshLayout.finishRefresh(PageRefreshLayout.kt:457) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefreshWithNoMoreData(SmartRefreshLayout.java:3056) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$6.run(SmartRefreshLayout.java:2994) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefresh(SmartRefreshLayout.java:3043) at com.drake.brv.PageRefreshLayout.finishRefresh(PageRefreshLayout.kt:457) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishRefreshWithNoMoreData(SmartRefreshLayout.java:3056) at com.scwang.smart.refresh.layout.SmartRefreshLayout.setNoMoreData(SmartRefreshLayout.java:2855) at com.scwang.smart.refresh.layout.SmartRefreshLayout$7.run(SmartRefreshLayout.java:3134) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMore(SmartRefreshLayout.java:3226) at com.drake.brv.PageRefreshLayout.finishLoadMore(PageRefreshLayout.kt:480) at com.scwang.smart.refresh.layout.SmartRefreshLayout.finishLoadMoreWithNoMoreData(SmartRefreshLayout.java:3239) at com.dhgate.buyermob.ui.order.DHOrderCenterRepeatFragment.initObserve$lambda-9$lambda-8(DHOrderCenterRepeatFragment.kt:274) at com.dhgate.buyermob.ui.order.DHOrderCenterRepeatFragment.$r8$lambda$nnS4UzGBLgrr3FPso16Izi2xGG0() at com.dhgate.buyermob.ui.order.DHOrderCenterRepeatFragment$$ExternalSyntheticLambda4.onChanged(:4) at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133) at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151) at androidx.lifecycle.LiveData.setValue(LiveData.java:309) at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50) at androidx.lifecycle.LiveData$1.run(LiveData.java:93) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8757) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
版本