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

在Handler队列里面执行引发的【java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState】 #863

Closed
Jiiiiiin opened this issue May 10, 2018 · 5 comments

Comments

@Jiiiiiin
Copy link

Jiiiiiin commented May 10, 2018

我们使用bugtags收集到一个如下的崩溃日志,目前线上项目使用的lib版本是:

ext.ANDROID_SUPPORT_LIBRARY_VERSION = "27.1.1"

dependencies {
    // ..... 省略
    // Android Support包
    api 'com.android.support:support-v4:' + ANDROID_SUPPORT_LIBRARY_VERSION
    api 'com.android.support:appcompat-v7:' + ANDROID_SUPPORT_LIBRARY_VERSION
    api 'com.android.support:design:' + ANDROID_SUPPORT_LIBRARY_VERSION
    api 'com.android.support:cardview-v7:' + ANDROID_SUPPORT_LIBRARY_VERSION


    // Fragmentation https://github.com/YoKeyword/Fragmentation/releases
    api 'me.yokeyword:fragmentation:1.3.3'
    api 'me.yokeyword:fragmentation-swipeback:1.3.3'

收集日志截图:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
	at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManagerImpl.java:2053)
	at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManagerImpl.java:2079)
	at android.support.v4.app.FragmentManagerImpl.popBackStack(FragmentManagerImpl.java:791)
	at android.support.v4.app.FragmentationMagician$1.run(FragmentationMagician.java:87)
	at android.support.v4.app.FragmentationMagician.hookStateSaved(FragmentationMagician.java:183)
	at android.support.v4.app.FragmentationMagician.popBackStackAllowingStateLoss(FragmentationMagician.java:84)
	at me.yokeyword.fragmentation.TransactionDelegate$6.run(TransactionDelegate.java:171)
	at me.yokeyword.fragmentation.queue.ActionQueue.handleAction(ActionQueue.java:53)
	at me.yokeyword.fragmentation.queue.ActionQueue.enqueueAction(ActionQueue.java:45)
	at me.yokeyword.fragmentation.queue.ActionQueue.access$000(ActionQueue.java:17)
	at me.yokeyword.fragmentation.queue.ActionQueue.access$100(ActionQueue.java:17)
	at me.yokeyword.fragmentation.queue.ActionQueue$1.run(ActionQueue.java:37)
	at android.os.Handler.handleCallback(Handler.java:739)
	at android.os.Handler.dispatchMessage(Handler.java:95)
	at android.os.Looper.loop(Looper.java:158)
	at android.app.ActivityThread.main(ActivityThread.java:7233)
	at java.lang.reflect.Method.invoke(Method.java)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

重现步骤:

感觉是应用从后台重新恢复到前台的时候爆出来的;

请问这种问题怎么解决呢?

而且这个异常没有被fragmention统一异常处理收集:

public final void configure() {
        initIcons();
        VP_CONFIGS.put(ConfigKeys.CONFIG_READY, true);
        final boolean isDebug = ViewPlus.IS_DEBUG();
        // 初始化Logger
        Logger.addLogAdapter(new AndroidLogAdapter());
        if (isDebug) {
            // 设置日志级别
            LoggerProxy.setLEVEL(LoggerProxy.DEBUG);
            // 建议在Application里初始化
            Fragmentation.builder()
                    // 显示悬浮球 ; 其他Mode:SHAKE: 摇一摇唤出   NONE:隐藏
                    .stackViewMode(Fragmentation.BUBBLE)
                    .debug(true)
                    // 在遇到After onSaveInstanceState时,不会抛出异常,会回调到下面的ExceptionHandler
                    .handleException(e -> {
                        // 建议在该回调处上传至我们的Crash监测服务器
                        // 以Bugtags为例子: 手动把捕获到的 Exception 传到 Bugtags 后台。
                        LoggerProxy.e(e, "Fragmentation 统一异常捕获发现错误");
                    })
                    .install();
        } else {
            // 设置日志级别
            LoggerProxy.setLEVEL(LoggerProxy.ERROR);
        }
        // 需要插件初始化完毕之后在进行初始化
        Utils.init((Application) ViewPlus.getApplicationContext());
    }

走的不是上面的渠道爆出来的

@williamwue
@YoKeyword

@Jiiiiiin
Copy link
Author

Jiiiiiin commented May 10, 2018

同样是从后台进入前台还出现另外一种问题:

java.lang.NullPointerException: There is no Fragment in the FragmentManager, maybe you need to call loadRootFragment() first!
	at me.yokeyword.fragmentation.TransactionDelegate$6.run(TransactionDelegate.java:158)
	at me.yokeyword.fragmentation.queue.ActionQueue.handleAction(ActionQueue.java:53)
	at me.yokeyword.fragmentation.queue.ActionQueue.enqueueAction(ActionQueue.java:45)
	at me.yokeyword.fragmentation.queue.ActionQueue.access$000(ActionQueue.java:17)
	at me.yokeyword.fragmentation.queue.ActionQueue.access$100(ActionQueue.java:17)
	at me.yokeyword.fragmentation.queue.ActionQueue$1.run(ActionQueue.java:37)
	at android.os.Handler.handleCallback(Handler.java:739)
	at android.os.Handler.dispatchMessage(Handler.java:95)
	at android.os.Looper.loop(Looper.java:135)
	at android.app.ActivityThread.main(ActivityThread.java:5401)
	at java.lang.reflect.Method.invoke(Method.java)
	at java.lang.reflect.Method.invoke(Method.java:372)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:919)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:714)

现在的执行代码是这样的,麻烦大佬帮忙看看是否存在问题:

public abstract class AbstractProxyActivity extends SupportActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initContainer(savedInstanceState);
    }

    /**
     * 返回根Delegate
     *
     * @return
     */
    public abstract AbstractViewPlusDelegate setRootDelegate();

    private void initContainer(@Nullable Bundle savedInstanceState) {
        final ContentFrameLayout container = new ContentFrameLayout(this);
        container.setId(R.id.delegate_container);
        setContentView(container);
        if (savedInstanceState == null) {
            // 初次加载主入口activity的时候设置根Delegate
            loadRootFragment(R.id.delegate_container, setRootDelegate());
        }
    }

@YoKeyword
Copy link
Owner

YoKeyword commented May 17, 2018

@Jiiiiiin 找到了原因, support v27.1.1 检查StateLoss的机制变了

    @Override
    public boolean isStateSaved() {
        return mStateSaved || mStopped; // 在27.1.1之前,只检查mStateSaved
    }

在Fragmentation FragmentationMagician

    private static void hookStateSaved(FragmentManager fragmentManager, Runnable runnable) {
        ...
        if (isStateSaved(fragmentManager)) {
            fragmentManagerImpl.mStateSaved = false; // 在之前版本中hack了该参数,让其绕过检查
            runnable.run();
            fragmentManagerImpl.mStateSaved = true;
        } else {
            runnable.run();
        }
    }

暂时提供2个方案:
1、退回27.1.0
2、不要在Fragment onStop()后出栈,保证Fragment在可见时出栈

PS: 后续我会看下mStop的作用,如果可行,会考虑同时hack

另外:
java.lang.NullPointerException: There is no Fragment in the FragmentManager, maybe you need to call loadRootFragment() first!

该异常只会出现在 startWithPop() 或者startWithPopTo()时, 先排查异常发生的位置

@YoKeyword
Copy link
Owner

v1.3.4兼容了该问题

@Jiiiiiin
Copy link
Author

@YoKeyword thx

@wilsonssss
Copy link

support 28.0.0 comes up again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants