您可以将基于 Compose 的界面添加到采用基于 View 的设计的现有应用中。
如需创建完全基于 Compose 的新屏幕,请让 activity 调用 setContent()
方法,并传递您想要使用的任何可组合函数。
class ExampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // In here, we can call composables! MaterialTheme { Greeting(name = "compose") } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }
这段代码看起来就和只含 Compose 元素的应用中的代码一样。
ViewCompositionStrategy
“ComposeView
”
默认情况下,只要视图与窗口分离,Compose 就会处理组合。Compose 界面 View
类型(例如 ComposeView
和 AbstractComposeView
)使用定义此行为的 ViewCompositionStrategy
。
默认情况下,Compose 使用 DisposeOnDetachedFromWindowOrReleasedFromPool
策略。但是,在 Compose 界面 View
类型用于以下各项的部分情况下,您可能并不希望使用此默认值:
Fragment。组合必须遵循 fragment 的视图生命周期,Compose 界面
View
类型才能保存状态。转换。每当在转换过程中使用 Compose 界面
View
时,系统都会在转换开始(而不是转换结束)时将其与窗口分离,从而导致您的可组合项在它仍然在屏幕上时处理其状态。您自己的由生命周期管理的自定义
View
。
在上述某些情况下,除非您手动调用 AbstractComposeView.disposeComposition
,否则应用还可能会因为组合实例缓慢泄漏内存。
如需在不再需要组合时自动处理组合,请通过调用 setViewCompositionStrategy
方法设置其他策略或创建自己的策略。例如,DisposeOnLifecycleDestroyed
策略会在 lifecycle
被销毁时处理组合。此策略适用于与已知的 LifecycleOwner
具有一对一关系的 Compose 界面 View
类型。当 LifecycleOwner
未知时,您可以使用 DisposeOnViewTreeLifecycleDestroyed
。
如需了解如何使用此 API,请参阅 fragment 中的 ComposeView
。
Fragment 中的 ComposeView
如果您要将 Compose 界面内容并入 fragment 或现有 View 布局,请使用 ComposeView
并调用其 setContent()
方法。ComposeView
是一个 Android View
。
您可以将 ComposeView
放在 XML 布局中,就像放置其他任何 View
一样:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/hello_world"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello Android!" />
<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
在 Kotlin 源代码中,通过 XML 中定义的布局资源使布局膨胀。然后,使用 XML ID 获取 ComposeView
,设置最适合宿主 View
的组合策略,并调用 setContent()
以使用 Compose。
class ExampleFragment : Fragment() { private var _binding: FragmentExampleBinding? = null // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentExampleBinding.inflate(inflater, container, false) val view = binding.root binding.composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } override fun onDestroyView() { super.onDestroyView() _binding = null } }
图 1. 此图显示了在 View 界面层次结构中添加 Compose 元素的代码的输出。“Hello Android!”文本由 TextView
微件显示。“Hello Compose!”文本由 Compose 文本元素显示。
如果整个屏幕是使用 Compose 构建的,您还可以直接在 fragment 中添加 ComposeView
,这样可让您完全避免使用 XML 布局文件。
class ExampleFragmentNoXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { MaterialTheme { // In Compose world Text("Hello Compose!") } } } } }
同一布局中的多个 ComposeView
实例
如果同一布局中存在多个 ComposeView
元素,每个元素必须具有唯一的 ID 才能使 savedInstanceState
发挥作用。
class ExampleFragmentMultipleComposeView : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = LinearLayout(requireContext()).apply { addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_x // ... } ) addView(TextView(requireContext())) addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_y // ... } ) } }
ComposeView
ID 在 res/values/ids.xml
文件中进行定义:
<resources>
<item name="compose_view_x" type="id" />
<item name="compose_view_y" type="id" />
</resources>
后续步骤
现在,您已经了解了在 View 中使用 Compose 的互操作性 API,接下来不妨了解如何在 Compose 中使用 View。