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)