我似乎正在与竞争条件作斗争,其原因似乎无法确定。执行下面的代码时,我会间歇性地获得下面的堆栈跟踪。
是否有一些明显的片段生命周期规则我不服从?我不清楚明确禁止我在这里执行交易来处理事件。
我正在使用WebViewClient
来检测在本地.html文档中点击的外部网址 - 例如,指向非本地主机的网址。我正在使用Otto的EventBus
将这些操作发布到Activity
。当Activity
收到这些事件时,我想通过调用Fragment
FragmentTransaction.replace()
中显示这些外部网址
DefaultWebViewClient.java
@Override
public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
boolean shouldOverride;
if (urlIsLocal(url)) {
shouldOverride = super.shouldOverrideUrlLoading(view, url);
} else {
// trigger an event for the fragment to swap out
// return true to tell the webview not to load it...
EventBus.getInstance().post(new LoadExternalUrlEvent(url));
shouldOverride = true;
}
return shouldOverride;
}
FragmentActivity.java
@Subscribe
public void onLoadExternalUrlEvent(LoadExternalUrlEvent externalLoadEvent) {
final BrowserFragment browserFragment = new BrowserFragment();
Bundle args = new Bundle();
args.putSerializable(BrowserFragment.ARG_LOAD_EXTERNAL_URL_EVENT, externalLoadEvent);
browserFragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, browserFragment, BrowserFragment.FRAGMENT_TAG)
.addToBackStack(null).commit();
}
LoadExternalUrlEvent.java
public class LoadExternalUrlEvent implements Serializable {
private static final long serialVersionUID = 1L;
public final String url;
public LoadExternalUrlEvent(String url) {
this.url = url;
}
@Override
public String toString() {
return "LoadExternalUrlEvent [url=" + url + "]";
}
}
EventBus.java
import com.squareup.otto.Bus;
public class EventBus {
private static Bus _INSTANCE;
public static synchronized Bus getInstance() {
if (null == _INSTANCE) {
_INSTANCE = new Bus();
}
return _INSTANCE;
}
}
堆栈跟踪
java.lang.RuntimeException: Could not dispatch event: class <omitted>.LoadExternalUrlEvent to handler [EventHandler public void <omitted>Activity.onLoadExternalUrlEvent(<omitted>LoadExternalUrlEvent)]: Can not perform this action after onSaveInstanceState
at com.squareup.otto.Bus.throwRuntimeException(Bus.java:456)
at com.squareup.otto.Bus.dispatch(Bus.java:386)
at com.squareup.otto.Bus.dispatchQueuedEvents(Bus.java:367)
at com.squareup.otto.Bus.post(Bus.java:336)
at <omitted>DefaultWebViewClient.shouldOverrideUrlLoading(DefaultWebViewClient.java:51)
at com.android.webview.chromium.WebViewContentsClientAdapter.shouldOverrideUrlLoading(WebViewContentsClientAdapter.java:293)
at com.android.org.chromium.android_webview.AwContentsClientBridge.shouldOverrideUrlLoading(AwContentsClientBridge.java:96)
at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1360)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1378)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
at <omitted>Activity.run(<omitted>Activity.java:162)
at <omitted>Activity.onLoadExternalUrlEvent(<omitted>Activity.java:156)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.squareup.otto.EventHandler.handleEvent(EventHandler.java:89)
at com.squareup.otto.Bus.dispatch(Bus.java:384)
... 15 more
A/libc(2689): Fatal signal 6 (SIGABRT) at 0x00000a81 (code=-6), thread 2689
答案 0 :(得分:7)
我发现了这个问题。
因为我在EventBus.register()
中呼叫Activity.onCreate()
我在我的后台堆上获得了Activity
的多个实例,这些实例将充当这些事件的响应者。
解决方案是尽可能晚地注册Activity
@Override
protected void onResume() {
super.onResume();
EventBus.getInstance().register(this);
}
@Override
protected void onPause() {
EventBus.getInstance().unregister(this);
super.onPause();
}
或使用
将您的Activity
声明为单个实例
android:launchMode="singleTask"