You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android手机中Compose DialogFragment重复渲染问题求助

问题:Jetpack Compose Popover在手机端出现视图残留、阴影加深及内存增长问题

我们的遗留项目基于1.0.0 AppCompatActivity,计划在新功能中使用Jetpack Compose实现一个悬浮于Activity内容上方、非全屏且带阴影的popover组件。为此采用全屏DialogFragment嵌入ComposeView的方案,核心代码如下:

class MyDialogFragment : AppCompatDialogFragment() {

    private val dismiss: () -> Unit = { this.dismiss() }
    private lateinit var tapPoint: Point

    fun initialize(tapPoint: Point) {
        this.tapPoint = tapPoint
    }

    @OptIn(ExperimentalPagerApi::class)
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return ComposeView(requireContext()).apply {
            setViewCompositionStrategy(DisposeOnViewTreeLifecycleDestroyed)
            setContent {
                MyDialogScreen(
                    dismiss = dismiss
                )
            }
        }
    }

    fun show(manager: FragmentManager) {
        super.show(manager, TAG)
        // the style only makes sure the fragment is displayed full-screen
        // <style name="MyDialogStyle">
        //     <item name="android:layout_width">match_parent</item>
        //     <item name="android:layout_height">wrap_content</item>
        //     <item name="android:windowSoftInputMode">adjustResize</item>
        // </style>
        this.setStyle(DialogFragment.STYLE_NO_TITLE, R.style.MyDialogStyle)
    }

    override fun onStart() {
        super.onStart()
        // This makes sure the full-screen dialog has a transparent background, so that the activity content could be seen behind the popover.
        dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog?.window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
    }

    companion object {
        const val TAG: String = "My Dialog"
        fun newInstance(tapPoint: Point): NotepadDialogFragment {
            return NotepadDialogFragment()
        }
    }
}

简化后的Composable代码如下:

@Composable
fun MyDialogScreen(
    dismiss: () -> Unit,
    tapPoint: Point
) {
    val windowInfo = rememberWindowInfo()
    MyTheme(
        windowInfo = windowInfo,
    ) {
        Column(modifier = Modifier.fillMaxSize()) {
            if (shouldPinToBottom(windowInfo = windowInfo, tapPoint = tapPoint)) {
                Spacer(modifier = Modifier.weight(1f))
            }
            Column(
                modifier = Modifier
                    .align(Alignment.CenterHorizontally)
                    .width(width = LocalCustomShape.current.width)
                    .height(height = LocalCustomShape.current.height)
                    .aspectRatio(
                        ratio = LocalCustomShape.current.width / LocalCustomShape.current.height,
                        matchHeightConstraintsFirst = true
                    )
                    .padding(LocalCustomShape.current.padding)
                    .drawColoredShadow(
                        color = LocalCustomColors.current.shadowColor,
                        shadowRadius = LocalCustomShape.current.shadowRadius,
                        cornerRadius = LocalCustomShape.current.cornerRadius
                    )
            ) {
                MyDialogContent()
            }
        }
    }
}

@Composable
fun MyDialogContent() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.White)
            .clip(RoundedCornerShape(LocalCustomShape.current.cornerRadius))){
        BasicTextField(
            value = "Hello world",
            onValueChange = {},
            modifier = Modifier
                .background(LocalCustomColors.current.textEditorBackground)
                .fillMaxWidth()
                .fillMaxHeight()
                .padding(all = 16.dp),
            textStyle = LocalCustomTypography.current.textEditor,
        )
    }
}

private fun shouldPinToBottom(windowInfo: MyWindowInfo, tapPoint: Point): Boolean {
    return windowInfo.screenWidthInfo != MyWindowInfo.WindowType.Compact
            && windowInfo.screenHeightInfo != MyWindowInfo.WindowType.Compact
            && tapPoint.y < windowInfo.screenHeight * HEIGHT_RATIO
}

异常现象

  • Android 9/11平板运行正常,但Android 9/12手机上出现问题:每次触摸文本编辑框,对话框阴影逐渐加深;键盘弹出导致popover尺寸变化时,旧视图残留于界面。
  • 模拟器中问题更严重,甚至出现十余个重复popover、Activity倒置的情况。

已做排查

  • App Inspector中始终仅显示一个Composable组件,重组检测结果正常。
  • 尝试Compose版本1.0.0至1.2.0 beta,均未解决问题。
  • 内存分析显示手机端内存持续增长,平板端则保持稳定。

恳请同行帮忙分析问题原因并提供解决方案。

内容的提问来源于stack exchange,提问作者user7907830

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 18:39:28