android - 显示 DialogFragment 会引发 "Can not perform this action after onSaveInstanceState"错误

标签 android module appcelerator appcelerator-titanium dialogfragment

问题

嗨,我正在为 Titanium 创建一个 Android 和 iOS 模块,它有一个 sendLog 方法,该方法将一些任意 JSON 数据发送到服务器,并在与某些预定义过滤器匹配时返回一个 URL。 URL 应在带有 Web View 的模态对话框中打开。

我编写了原生 iOS 和 Android 库,并将它们包装为 Titanium 模块。在 iOS 上一切正常,但在 Android 上我无法打开对话框(请参阅下面的错误堆栈跟踪)。现在,有一条日志消息始终会触发同一网页以进行测试。在 Android 上,它只是默默地失败。

测试用例

var mupets = require("be.iminds.mupets");
mupets.initialize("wappr", "http://tocker.iminds.be:3000/log/report.json", 1, 100, 3);
var esmLog = { 
    bar: "foo"
};
mupets.sendLog("es-test-01",JSON.stringify(esmLog));

在这段代码之后(最多大约 10 秒后),模块应该显示一个 native 对话框,其中包含以下网页:http://tocker.iminds.be:3000/es/sheets/test-01/index.html

相反,这是我一直收到的错误:

日志

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1411)
at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1429)
at android.app.BackStackRecord.commitInternal(BackStackRecord.java:687)
at android.app.BackStackRecord.commit(BackStackRecord.java:663)
at android.app.DialogFragment.show(DialogFragment.java:256)
at be.iminds.mupets_client_android.logging.plugins.OutHttp.getEsm(OutHttp.java:122)
at be.iminds.mupets_client_android.logging.plugins.OutHttp$1.success(OutHttp.java:78)
at be.iminds.mupets_client_android.HttpClient$1$1.onResponse(HttpClient.java:76)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:133)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)

以下是导致错误的 Android 代码:

Activity activity = (Activity) context;
                EsmDialogFragment esmDialogFragment = EsmDialogFragment.newInstance(new EsmDialogListener() {
                    @Override
                    public void submit(String type, JsonObject result) {
                        Mupets.sendLog(type, result);
                        esmShown = false;
                    }

                    @Override
                    public void onCancel(JsonObject cancelled) {
                        super.onCancel(cancelled);
                        Mupets.sendLog("ESM_cancelled", cancelled);
                        esmShown = false;
                    }
                }, url, true);
                FragmentTransaction transaction = activity.getFragmentManager().beginTransaction();
                Fragment prev = activity.getFragmentManager().findFragmentByTag(EsmDialogFragment.ESM_DIALOG_FRAGMENT);
                if (prev != null) {
                    transaction.remove(prev);
                }
                transaction.addToBackStack(null);
                Log.v(TAG, "Pre-show fragment");
                esmDialogFragment.show(transaction, EsmDialogFragment.ESM_DIALOG_FRAGMENT);
                Log.v(TAG, "Post-show fragment");

Titanium 是否不允许使用 Fragment/或要求您在特定点调用 Dialog.show() ?该错误涉及“...after onSaveInstanceState”,但我不知道如果我没有创建 Activity ,如何在 onSaveInstanceState 之前调用它,也不知道为什么当我在 native Android 应用程序中使用它时代码可以工作。

这是一个 Titanium 示例项目,其模块在打开后应显示对话框: https://www.dropbox.com/s/0v77xd5gllv6kb3/testModule.zip?dl=1

最佳答案

这不是一个小问题,因此没有快速且简单的解决方案,您只需从答案中复制/粘贴即可。最重要的是,您将必须重构一些代码。

您正在尝试显示 DialogFragment 以响应异步操作 - 如果该操作在 onSaveInstanceState 之后完成,回调将尝试显示对话框并引发 IllegalStateException

保护自己免受此问题影响的方法是不要直接通过回调执行 UI 操作。相反,您需要暂停,直到启动或恢复 ActivityFragment,以便可以安全地显示对话框。

实现此目的的一个简单方法是使用粘性事件,即从回调中发布粘性事件,并在 UI 组件的 onResume 方法中订阅该类型的粘性事件。

如果您不想使用事件总线库,则可以从非 UI 组件调用异步方法,该方法会在回调中更新其内部状态,然后让 UI 组件在 中检查该状态>onResume。如果您使用这种方法,则需要小心管理全局状态。

关于android - 显示 DialogFragment 会引发 "Can not perform this action after onSaveInstanceState"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37429953/

相关文章:

android - 无法在 hexagon-dsp : cannot link executable library adsprpc. lib 中执行示例

以非 root 用户身份运行时 Perl 模块无法正确加载

android - Titanium 1.8 是否终于摆脱了 1.6 和 1.7 版的内存不足问题

html - 如何使用 css 模块设置 webpack

IOS 跨设备唯一用户标识符

javascript - 为什么我的应用程序无法在 TableView 中显示 JSON 数据?

android - 如何挂断(断开连接、终止...)来电?

android - 将图片从图库上传到android中的服务器

android - 使用Android Vision扫描pdf417条码获取字节数组

java - Netbeans:我可以将 Apache Felix 用于家庭维护的 Java 库存储库吗?