Android共享元素转场出现NullPointerException问题求助
解决Fragment共享元素转场的NullPointerException问题
这个空指针问题我之前在处理Android 6.0-8.0版本的共享元素转场时也遇到过,核心原因是系统在处理共享元素转场时,对应的源View已经被从视图树中移除,导致调用transformMatrixToLocal时拿到了null对象。结合你的代码来看,问题出在同一个Fragment事务中同时做了两件事:添加带有共享元素转场的新Fragment,以及移除包含源ImageView的mainFragment——移除操作会立即把源ImageView从视图树中销毁,转场逻辑执行时就会找不到这个View,抛出NPE。
下面是具体的解决方案:
1. 延迟移除源Fragment,避免破坏转场依赖的View
不要在添加新Fragment的同一个事务中移除mainFragment,而是等共享元素转场完成后再执行移除操作。可以通过给转场添加监听器来实现:
override fun onLoadUrl(url: String, source: String, imageView: ImageView?, drawableRes: Int) { val tabBean = MultiWindowManager.getForegroundTab()!! val transaction = supportFragmentManager.beginTransaction() var fragment = supportFragmentManager.findFragmentByTag(tabBean.tabId) as? WebFragment if (fragment != null) { transaction.show(fragment).commitAllowingStateLoss() fragment.loadUrl(url, source) } else { fragment = WebFragment.newInstance(url, tabBean.tabId, source, drawableRes) if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { fragment.sharedElementEnterTransition = DetailTransition() fragment.exitTransition = Fade() fragment.enterTransition = Fade() fragment.sharedElementReturnTransition = DetailTransition() // 添加转场监听器,延迟移除mainFragment fragment.sharedElementEnterTransition.addListener(object : Transition.Listener { override fun onTransitionStart(transition: Transition?) {} override fun onTransitionEnd(transition: Transition?) { // 转场完成后安全移除源Fragment supportFragmentManager.beginTransaction() .remove(mainFragment) .commitAllowingStateLoss() } override fun onTransitionCancel(transition: Transition?) { // 转场取消时也要移除,避免内存泄漏 supportFragmentManager.beginTransaction() .remove(mainFragment) .commitAllowingStateLoss() } override fun onTransitionPause(transition: Transition?) {} override fun onTransitionResume(transition: Transition?) {} }) } // 事务中只添加新Fragment和共享元素,不执行remove操作 transaction.add(R.id.frameContainer, fragment, tabBean.tabId) // 额外检查:确保ImageView已附加到视图树 imageView?.takeIf { it.isAttachedToWindow }?.let { transaction.addSharedElement(it, getString(R.string.shared_recommend)) } transaction.commitAllowingStateLoss() } webFragment = fragment updateFragmentType(FRAGMENT_WEB) }
2. 确保目标Fragment存在匹配的共享元素
检查WebFragment的布局文件,确认存在一个View的transitionName和源ImageView的一致(即@string/shared_recommend),比如:
<ImageView android:id="@+id/target_image" android:layout_width="match_parent" android:layout_height="wrap_content" android:transitionName="@string/shared_recommend" />
如果目标Fragment没有对应的共享元素,系统也可能在转场过程中出现异常,这是容易忽略的点。
3. 添加安全校验,避免无效的共享元素
在添加共享元素前,通过isAttachedToWindow检查ImageView是否还存在于视图树中,避免将已被销毁或分离的View作为共享元素传入,这能进一步降低空指针的概率(代码中已经包含这部分)。
这些修改后,就能保证共享元素转场过程中,源View始终存在,不会被提前销毁,从而解决你遇到的NullPointerException问题。
内容的提问来源于stack exchange,提问作者wang willway
相关产品推荐
相关产品推荐

