From cf527db60e749ba67232c9fc784eb21744d243bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=BE=E7=A5=A5=E4=BF=8A?= Date: Thu, 7 Nov 2024 13:42:39 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20Sentry-418688=20SearchActivity=E5=9B=9E?= =?UTF-8?q?=E8=B0=83onSavedInstance=E5=90=8E=EF=BC=8C=E8=B0=83=E7=94=A8Fra?= =?UTF-8?q?gmentManager=E7=9A=84popBackStack=E5=BC=95=E5=8F=91=E7=9A=84?= =?UTF-8?q?=E5=B4=A9=E6=BA=83=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gh/common/fragment/FragmentManagerExt.kt | 74 +++++++++++++++++++ .../java/com/gh/gamecenter/SearchActivity.kt | 3 +- 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/gh/common/fragment/FragmentManagerExt.kt diff --git a/app/src/main/java/com/gh/common/fragment/FragmentManagerExt.kt b/app/src/main/java/com/gh/common/fragment/FragmentManagerExt.kt new file mode 100644 index 0000000000..27313e54ee --- /dev/null +++ b/app/src/main/java/com/gh/common/fragment/FragmentManagerExt.kt @@ -0,0 +1,74 @@ +package com.gh.common.fragment + +import androidx.fragment.app.FragmentManager +import java.lang.reflect.Field + +fun FragmentManager.popBackStackAllowStateLoss() { + popBackStackAllowStateLoss(-1, 0) +} + +fun FragmentManager.popBackStackAllowStateLoss(id: Int, flags: Int) { + if (!isStateSaved) { + popBackStack(id, flags) + } else { + hook { popBackStack(id, flags) } + } +} + +fun FragmentManager.popBackStackAllowStateLoss(name: String?, flags: Int) { + if (!isStateSaved) { + popBackStack(name, flags) + } else { + hook { popBackStack(name, flags) } + } +} + +fun FragmentManager.popBackStackImmediateAllowStateLoss() = popBackStackAllowStateLoss(-1, 0) + +fun FragmentManager.popBackStackImmediateAllowStateLoss(id: Int, flags: Int) = + if (!isStateSaved) { + popBackStackImmediate(id, flags) + } else { + hook { popBackStackImmediate(id, flags) } + } + +fun FragmentManager.popBackStackImmediateAllowStateLoss(name: String?, flags: Int): Boolean = + if (!isStateSaved) { + popBackStackImmediate(name, flags) + } else { + hook { popBackStackImmediate(name, flags) } + } + +/** + * 通过反射将FragmentManager的mStateSaved和mStopped设为false,否则Activity在回调onSavedInstance以后, + * 调用Fragment的popBackStack和popBackStackImmediate方法会触发“java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState”的异常。 + * @see Sentry-418688 + */ +private fun FragmentManager.hook(callback: FragmentManager.() -> T): T { + val mStateSavedField = getField(this::class.java,"mStateSaved") + val stateSaved = mStateSavedField.get(this); + mStateSavedField.set(this, false) + val mStoppedField = getField(this::class.java,"mStopped") + val stopped = mStateSavedField.get(this); + mStoppedField.set(this, false) + val result = callback.invoke(this) + mStateSavedField.set(this, stateSaved) + mStoppedField.set(this, stopped) + return result +} + +@Throws(NoSuchFieldException::class) +private fun getField(clazz: Class<*>, name: String): Field { + var cls: Class<*>? = clazz + while (cls != null) { + try { + val declaredField = cls.getDeclaredField(name) + declaredField.isAccessible = true + return declaredField + } catch (e: NoSuchFieldException) { + e.printStackTrace() + } + cls = cls.superclass + } + throw NoSuchFieldException() +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/SearchActivity.kt b/app/src/main/java/com/gh/gamecenter/SearchActivity.kt index 595af14aa2..684aefa259 100644 --- a/app/src/main/java/com/gh/gamecenter/SearchActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/SearchActivity.kt @@ -15,6 +15,7 @@ import androidx.core.widget.doAfterTextChanged import androidx.core.widget.doOnTextChanged import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction +import com.gh.common.fragment.popBackStackAllowStateLoss import com.gh.common.util.DataCollectionUtils import com.gh.common.util.LogUtils import com.gh.gamecenter.DisplayType.* @@ -381,7 +382,7 @@ open class SearchActivity : BaseActivity() { } protected fun popBackToFragment(tag: String) { - supportFragmentManager.popBackStack(tag, 0) + supportFragmentManager.popBackStackAllowStateLoss(tag, 0) } @Subscribe(threadMode = ThreadMode.MAIN)