View=android.widget.ZoomButtonsController$Container not attached to window manager

本文探讨了WebView组件中ZoomButtonsController导致的应用崩溃问题,并提供了解决方案。通过禁用内置缩放控件并调整WebSettings设置来避免崩溃,同时确保了应用的稳定性和兼容性。

bug 信息如图:
这里写图片描述

搜索 ZoomButtonsController 之后几乎所有的问题都指向: WebView

看下 WebActivity,这个版本为了兼容合作公司的网页,加了一堆配置

        webview.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webview.getSettings().setBuiltInZoomControls(true);
        webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        webview.getSettings().setAllowFileAccess(true);
        webview.getSettings().setSupportZoom(true);
        webview.getSettings().setUseWideViewPort(true);
        webview.getSettings().setSupportMultipleWindows(true);
        webview.getSettings().setAppCacheEnabled(true);
        webview.getSettings().setDomStorageEnabled(true);
        webview.getSettings().setGeolocationEnabled(true);
        webview.getSettings().setAppCacheMaxSize(Long.MAX_VALUE);
        webview.getSettings().setPluginState(WebSettings.PluginState.ON_DEMAND);
        webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

问题应该就出在这里,按照这篇文章中的说法:
webview ZoomButtonsController 调用崩溃问题android.widget.ZoomButtonsController,在调用 webView.destroy() 之前,应该先调用: webview.setVisibility(View.GONE) ,不过之后在这篇文章中又提到部分手机不兼容的问题,那么,事实上原生 WebView 的 ZoomButton 巨丑,商量之后,果断禁用掉,还省去了一堆麻烦事:

        webview.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        webview.getSettings().setAllowFileAccess(true);
        webview.getSettings().setUseWideViewPort(true);
        webview.getSettings().setSupportMultipleWindows(true);
        webview.getSettings().setAppCacheEnabled(true);
        webview.getSettings().setDomStorageEnabled(true);
        webview.getSettings().setGeolocationEnabled(true);
        webview.getSettings().setAppCacheMaxSize(Long.MAX_VALUE);
        webview.getSettings().setPluginState(WebSettings.PluginState.ON_DEMAND);
        webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

        webview.getSettings().setBuiltInZoomControls(false);
        webview.getSettings().setSupportZoom(flase);
Android 开发中,使用 `Switch` 控件时如果遇到 `java.lang.IllegalArgumentException: View not attached to window manager` 异常,通常是由于在非 UI 线程中操作了 UI 元素,或者尝试在 `Toast`、`Dialog` 显示时其关联的 `View` 已经被移除或未正确附加到窗口管理器。 ### 异常原因分析 该异常通常发生在尝试通过 `WindowManager` 操作一个未附加到窗口管理器的 `View`。例如,当在 `Activity` 或 `Fragment` 销毁后仍尝试显示 `Toast`,或在非主线程中更新 UI 时,就会触发 `WindowManagerGlobal.findViewLocked` 抛出异常的情况[^1]。 ### 解决方案 #### 1. 确保 UI 操作在主线程执行 所有与 UI 相关的操作必须在主线程中执行。如果在子线程中执行 UI 操作,应使用 `runOnUiThread` 方法切换到主线程: ```java runOnUiThread(() -> { // 更新 Switch 状态或显示 Toast switch1.setChecked(true); Toast.makeText(context, "状态已更改", Toast.LENGTH_SHORT).show(); }); ``` #### 2. 避免在 `onDestroy` 或 `onPause` 中操作 UI 在 `Activity` 或 `Fragment` 生命周期的 `onDestroy` 或 `onPause` 方法中,如果仍在执行异步任务(如网络请求、定时器),应取消这些任务以避免在视图销毁后尝试更新 UI[^2]。 #### 3. 使用 `Context` 时确保其有效性 当使用 `Context` 显示 `Toast` 或构建 `Dialog` 时,应确保该 `Context` 仍然有效。避免在异步回调中持有已销毁的 `Activity` 的引用。可以使用弱引用(`WeakReference`)来避免内存泄漏: ```java private WeakReference<Context> contextRef; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.switch_layout); contextRef = new WeakReference<>(this); } private void showToast() { Context context = contextRef.get(); if (context != null && !isFinishing()) { Toast.makeText(context, "开关状态改变", Toast.LENGTH_SHORT).show(); } } ``` #### 4. 在 `Switch` 状态变化时避免重复操作 确保在 `Switch` 的 `setOnCheckedChangeListener` 中不要重复触发可能导致 UI 状态变化的操作,避免死循环或重复更新视图。 ### 示例代码 以下是一个完整的 `Switch` 使用示例,包含避免异常的处理逻辑: ```java Switch switch1 = findViewById(R.id.switch1); switch1.setOnCheckedChangeListener((buttonView, isChecked) -> { if (isChecked) { runOnUiThread(() -> Toast.makeText(buttonView.getContext(), "开关打开", Toast.LENGTH_SHORT).show()); } else { runOnUiThread(() -> Toast.makeText(buttonView.getContext(), "开关关闭", Toast.LENGTH_SHORT).show()); } }); ``` ### 异常预防建议 - 在涉及异步操作的场景中,始终检查 `Activity` 是否处于活动状态。 - 使用 `Handler` 或 `LiveData` 替代直接的 UI 操作,以更好地管理生命周期。 - 避免在 `Toast` 或 `Dialog` 显示前其关联的 `Context` 已被销毁。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值