gpt4 book ai didi

Android - 如何在使用应用程序上下文创建 WebView 后将其附加到 Activity

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:24:11 25 4
gpt4 key购买 nike

我正在使用应用程序上下文在后台创建一个 Android WebView,以便在我需要显示它时加载并准备就绪。我在需要时使用 addView 将它附加到我的 Activity。这在大多数情况下都很好用,但是当我尝试打开一个 HTML 选择下拉菜单时,我遇到了崩溃:

android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
at android.view.ViewRootImpl.setView(ViewRootImpl.java:540)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
at android.app.Dialog.show(Dialog.java:286)
at com.android.org.chromium.content.browser.input.SelectPopupDialog.show(SelectPopupDialog.java:217)
at com.android.org.chromium.content.browser.ContentViewCore.showSelectPopup(ContentViewCore.java:2413)
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:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
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:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)

我假设这是因为我使用 ApplicationContext 创建了 WebView。我的问题是:有没有办法解决这个问题?有没有办法将现有的 WebView“附加”到不同的 Activity 或 Window 以便可以创建 Dialog?有什么方法可以通过在运行时更改上下文来使用反射将其“破解”在一起吗?

编辑:如下所示,我使用 MutableContextWrapper 进行了测试它似乎很好地解决了这个问题!

最佳答案

所以,我们实际上遇到了同样的问题(在保留的 Fragment 中使用 WebView 来防止页面重新加载,同时不泄漏 Activity context) 简短的回答似乎是没有真正干净的方法可以做到这一点。我什至尝试了一个自定义的 WebView 子类,它返回主机 Activity 的窗口 token 而不是 WebView 自己的 token ,没有成功。

正如您所建议的,我们最终使用反射来修改底层上下文:

public static boolean setContext(View v, Context ctx) {
try {
final Field contextField = View.class.getDeclaredField("mContext");
contextField.setAccessible(true);
contextField.set(v, ctx);
return (v.getContext() == ctx);
} catch (IllegalAccessException | NoSuchFieldException e) {
Log.e(TAG, String.valueOf(e), e);
return false;
}
}

它只是在 View 实例上设置 mContext 字段,如果修改成功则返回 true。但是,我最近看到另一个建议(我还没有测试过,所以 YMMV)使用 MutableContextWrapper。因此,您可以使用 Activity Context 填充 WebView,并包装在 MutableContextWrapper 中。然后,当您需要释放之前的引用时,您可以将 WebViewContext 转换为 MutableContextWrapper,然后设置基Context 到新的 Activity。所以像这样的东西来膨胀布局:

MutableContextWrapper contextWrapper = new MutableContextWrapper(activity);

WebView webView = (WebView) LayoutInflater.from(contextWrapper)
.inflate(R.layout.your_webview_layout, theParent, false);

然后,重新附加到一个新的 Activity:

if (webView.getContext() instanceof MutableContextWrapper) {
((MutableContextWrapper) webView.getContext()).setBaseContext(newActivity);
}

关于Android - 如何在使用应用程序上下文创建 WebView 后将其附加到 Activity,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27994709/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com