android 2.x上Dialog特定情况导致无法dismiss的bug

本文讨论了在Android2.x到4.x版本中使用装饰模式构建对话框时遇到的异常崩溃问题。问题源于在style.xml中定义的对话框样式包含不兼容的窗口动画,导致系统崩溃。文章分析了问题原因,并提供了解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在做一个简单的对话框框架,作用仅仅是做出一个显示效果在android 2.x到android 4.x上均类似的对话框.

思路比较简单,就是使用装饰模式包裹Dialog,暴露的接口调用时会自动完成一些设置

但是遇到一个特别诡异的问题,在android 2.x上的Dialog对话框无法被dismiss,只要弹出来界面就卡死,强行使用eclipse重新run的话会导致android设备黑屏无响应,如果是模拟器,则直接崩溃,看到启动画面.而且这个还不是ANR错误.

后来通过删减代码找到了问题的源头,这也是最不可能被怀疑的地方.在style.xml中我定义了一个对话框用的style,继承@android:style/Theme.Dialog

<style name="Shalog" parent="@android:style/Theme.Dialog">
    <item name="android:windowAnimationStyle">@style/ShalogAnimation</item>
</style>

问题就出在这个android:windowAnimationStyle属性上,我给这个属性定义的ShalogAnimation给Dialog进入和退出分别设置了alpha动画,alpha动画在API 11及以上才支持,也就是android 3.0及以上版本.即便是这样,我还是无法理解这个问题.

我记得android对xml中不支持的内容是直接忽略的,所以理论上这个动画被忽略了才对,然而实际上却能让android整个系统崩溃掉,非常诡异.

如果换用translate动画,则表现正常.

我在stackoverflow上问了,暂时还没有人回答,他们有人评论说为什么还要兼容android 4.0以下版本.嗯,我以后绝对拒绝兼容.

这应该是个bug.如果有谁了解欢迎评论批评指正.

<think>我们正在解决的是在Fragment中调用WebLinksUtil.jumpToAppCompatibleProducts方法时可能出现的两个异常:1.ActivityNotFoundException:没有找到处理Intent的Activity2.IllegalArgumentException:可能涉及到视图ID找不到等问题(根据引用[2]和[3])针对第一个问题(ActivityNotFoundException)我们已经有了初步的解决方案,但需要完善和整合。针对第二个问题(IllegalArgumentException),从引用[2][^2]和引用[3][^3]中我们得知,可能是因为在Fragment中使用了错误的FragmentManager,导致视图ID找不到。但请注意,用户现在的问题集中在WebLinksUtil.jumpToAppCompatibleProducts方法的调用上,这个方法内部是启动一个Activity,所以第二个问题(IllegalArgumentException)可能不是由这个方法直接引起的,而是用户可能在Fragment中还执行了其他操作(比如Fragment事务)导致的。但是,为了确保全面性,我们应该检查所有可能。根据用户提供的引用,第二个问题(IllegalArgumentException:Noviewfoundforid)通常发生在Fragment事务中,即当我们尝试替换或添加一个Fragment到一个容器,但是该容器在当前Fragment的布局中不存在。这通常是因为:-使用了错误的FragmentManager:在Fragment内部进行子Fragment操作时,应该使用getChildFragmentManager()而不是getActivity().getSupportFragmentManager()(即getParentFragmentManager())然而,在用户的问题描述中,WebLinksUtil.jumpToAppCompatibleProducts方法内部只是启动一个Activity,不会直接导致视图ID找不到的异常。所以,用户可能同时遇到了两个独立的问题,或者启动Activity失败后,用户又尝试了其他操作导致了第二个异常。因此,我们将分别处理这两个问题。问题一:解决ActivityNotFoundException问题二:解决IllegalArgumentException(Noviewfoundforid)由于用户的问题集中在WebLinksUtil.jumpToAppCompatibleProducts方法上,我们先重点解决ActivityNotFoundException,然后给出解决IllegalArgumentException的建议(如果用户同时遇到)。问题一:ActivityNotFoundException的解决方案(在Fragment中调用跳转方法)我们已经分析过,可能的原因:1.上下文使用不当:在Fragment中使用ApplicationContext启动Activity,可能导致某些问题(虽然通常不会,但为了安全,建议使用ActivityContext)2.没有处理URL的协议头(如http/https)3.设备上没有安装可以处理该Intent的应用程序(如浏览器)4.AndroidManifest.xml中未声明目标Activity(如果是跳转内部Activity)我们在WebLinksUtil.jumpToAppCompatibleProducts方法中已经做了改进。但是,请注意,我们跳转的是通过浏览器打开的网页,所以目标Activity是浏览器,我们不需要在Manifest中声明浏览器(它是系统应用),但需要确保URL正确且有应用可以处理。问题二:IllegalArgumentException(Noviewfoundforid)根据引用[2][^2]和引用[3][^3],解决方案是使用正确的FragmentManager:-在Activity中操作Fragment:使用getSupportFragmentManager()-在Fragment中操作子Fragment:使用getChildFragmentManager()现在,我们针对问题一(ActivityNotFoundException)给出完整的解决方案,并在问题二的解决方案中给出使用FragmentManager的最佳实践。由于用户提供的引用[1]是关于Servlet的,与当前问题无关,忽略。整合后的回答:我们将分为两个部分:第一部分:解决ActivityNotFoundException(主要问题)第二部分:解决IllegalArgumentException(可能同时存在或用户后续会遇到的Fragment事务问题)注意:用户可能在调用跳转方法后,由于跳转失败,而尝试使用Fragment事务展示错误界面,这时如果使用错误的FragmentManager就会出现IllegalArgumentException。因此,我们给出完整的方案。</think> ### Fragment中WebLinksUtil.jumpToAppCompatibleProducts()错误的综合解决方案 #### 一、问题分析 1. **ActivityNotFoundException** - 当使用`requireContext()`时,获取的是Application Context而非Activity Context[^1] - URL协议头可能缺失,导致无法识别目标应用(如缺少`https://`前缀)[^5] - AndroidManifest未正确声明目标Activity 2. **IllegalArgumentException** - 使用错误的FragmentManager(应使用`childFragmentManager`替代`parentFragmentManager`)[^2] - Fragment事务中使用了不存在的视图ID ```mermaid graph TD A[Fragment调用] --> B{使用哪种Context?} B -->|requireContext| C[Application Context] B -->|activity| D[Activity Context] C --> E[ActivityNotFoundException] D --> F{URL协议头?} F -->|无协议| G[错误] F -->|https://| H[成功] ``` #### 二、具体解决方案 ##### 1. 修复ActivityNotFoundException ```kotlin // WebLinksUtil.kt fun jumpToAppCompatibleProducts(context: Context) { val validUrl = if (BuildConfig.APP_COMPATIBLE_PRODUCTS_URL.startsWith("http")) { BuildConfig.APP_COMPATIBLE_PRODUCTS_URL } else { "https://${BuildConfig.APP_COMPATIBLE_PRODUCTS_URL}" } val intent = Intent(Intent.ACTION_VIEW, Uri.parse(validUrl)).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } // 验证是否有可用浏览器 if (intent.resolveActivity(context.packageManager) != null) { context.startActivity(intent) } else { // 备用方案:使用内部WebView startWebViewActivity(context, validUrl) } } private fun startWebViewActivity(context: Context, url: String) { val intent = Intent(context, WebViewActivity::class.java).apply { putExtra("url", url) } context.startActivity(intent) } ``` ##### 2. 修复IllegalArgumentException ```kotlin // 在Fragment中正确使用 class MyFragment : Fragment() { fun openProducts() { // 使用Activity的context activity?.let { WebLinksUtil.jumpToAppCompatibleProducts(it) } } // 子Fragment事务使用childFragmentManager fun addChildFragment() { childFragmentManager.beginTransaction() .replace(R.id.fragment_container, ChildFragment()) .commit() } } ``` ##### 3. AndroidManifest配置 ```xml <activity android:name=".WebViewActivity" android:theme="@style/Theme.AppCompat.Light"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> ``` #### 三、最佳实践 1. **上下文使用规范**: ```kotlin // 安全获取Activity引用 activity?.let { // 执行操作 } ?: run { Timber.e("Activity is null") } ``` 2. **URL验证工具**: ```kotlin fun ensureUrlProtocol(url: String): String { return when { url.startsWith("http") -> url url.startsWith("www.") -> "https://$url" else -> "https://$url" } } ``` 3. **多版本兼容处理**: ```kotlin if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { intent.addFlags(Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER) } ``` 4. **视图ID重用检查**: ```kotlin // 在add/replace前验证容器视图存在 if (view?.findViewById<View>(R.id.fragment_container) != null) { childFragmentManager.beginTransaction() .replace(R.id.fragment_container, fragment) .commit() } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值