这个适合初学者的教程提供了一个如何将这个简单的 RecycleView 应用程序转换为 Jetpack Compose 的示例。
在迁移到 Jetpack Compose 后,我还采取了一些额外的步骤来清理未使用的代码或 xml。
1.删除RecycleView、Layout、Fragment和Library文件
除了RecycleView
,您还可以删除片段和布局文件,因为 Jetpack Compose 不需要它们。
删除不需要的源代码
MainFragment.kt
RecyceViewAdapter.kt
ItemViewHolder.kt
ItemDiffCallback.kt
删除不需要的布局文件
main_activity.xml
main_fragment.xml
item.xml
删除不需要的构建功能和库
在app\build.gradle
中,删除数据绑定,因为这不再适用于 Jetpack Compose。
buildFeatures {
dataBinding true
}
也删除这些依赖项。
dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
implementation 'androidx.fragment:fragment-ktx:1.4.0'
}
修复 MainActivity.kt 中的编译问题
删除此代码,MainActivity::onCreate()
因为您不再需要片段。
setContentView(R.layout.main_activity)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, MainFragment.newInstance())
.commitNow()
}
您现在应该能够成功构建。
2 设置 Jetpack Compose 库
更新 build.gradle(项目级别)
在内部添加compose_version
扩展名,buildScript{ }
以便以后可以引用撰写版本。
buildscript {
ext {
compose_version = '1.0.5'
}
...
}
更新 app\build.gradle(应用级别)
添加compose
构建功能和kotlinCompilerExtensionVersion
组合选项。
android {
....
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
}
....
}
替换implementation 'androidx.appcompat:appcompat:1.4.0'
为implementation 'androidx.activity:activity-compose:1.4.0'
并添加以下 Jetpack Compose 依赖项。
dependencies {
...
implementation 'androidx.activity:activity-compose:1.4.0'
...
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
...
}
为撰写更新 MainActivity
在 Jetpack Compose 中,你不再需要AppCompatActivity
了,你可以直接继承自ComponentActivity
修改MainActivity
为直接继承ComponentActivity
,覆盖onCreate()
和调用SetContent{}
,允许@composable
内部调用任何函数。
class MainActivity : ComponentActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// Implement composable function here.
}
}
}
3. 在 Jetpack Compose 中添加主题
在 Jetpack Compose 中添加主题之前,让我们清理一下colors.xml
和themes.xml
.
您只需要themes.xml
为 提供颜色android:statusBarColor
。所以你保留它并删除其他任何东西。
清理colors.xml 和themes.xml
这些应该是自定义状态栏颜色所需的最少代码。
color.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_700">#FF3700B3</color>
</resources>
themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.RecycleViewDemo" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
</style>
</resources>
themes.xml(夜间)
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.RecycleViewDemo" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
</style>
</resources>
添加撰写主题
创建ui.theme包文件夹,将Colors.kt
, Shape.kt
,Type.kt
放入该文件夹。
Colors.kt
val Purple200 = Color(0xFFBB86FC)
val Purple500 = Color(0xFF6200EE)
val Purple700 = Color(0xFF3700B3)
val Teal200 = Color(0xFF03DAC5)
Shape.kt
val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(4.dp),
large = RoundedCornerShape(0.dp)
)
Type.kt
val Typography = Typography(
body1 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
)
)
Theme.kt
private val DarkColorPalette = darkColors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200
)
private val LightColorPalette = lightColors(
primary = Purple500,
primaryVariant = Purple700,
secondary = Teal200
)
@Composable
fun RecycleViewDemoTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
这些文件允许您自定义 Jetpack Compose 的主题。
要为您的应用程序设置主题,请MainContent()
从RecycleViewDemoTheme
. 代码如下所示:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MainScreen()
}
}
}
@Composable
fun MainScreen() {
RecycleViewDemoTheme {
MainContent()
}
}
@Composable
fun MainContent() {
//Todo: Implement LazyColumn
}
4.添加顶部应用栏
由于您已删除AppCompatActivity
,因此不再创建顶部应用栏。您需要使用 Jetpack Compose 创建它。
添加 Scaffold() 可组合函数
要创建顶部应用栏,请使用ScaffoldI()
可组合功能。代码如下所示:
@Composable
fun MainScreen() {
RecycleViewDemoTheme {
Scaffold(
topBar = { TopAppBar (title = {Text(stringResource(R.string.app_name))})
}
) {
MainContent()
}
}
}
预览可组合函数
为了预览可组合函数,您添加以下代码:
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
MainScreen()
}
编译后,您应该会在右侧看到类似的内容。如果您运行您的应用程序,您应该会看到与预览版相同的 UI。
现在,该应用程序已完全使用 Jetpack Compose 代码实现。此时,UI 与没有回收视图内容的基于视图的 UI 方法完全相同。
5.实现LazyColumn可组合功能
RecycleView
Jetpack compose 中的等价物是LazyColumn
可组合函数。
严格来说,它们并不相同。LazyColumn
并没有真正回收项目 UI。它只是重新创建整个项目 UI。所以理论上RecycleView
性能应该比LazyColumn
.
它的好处是LazyColumn
使用更少的代码,因为RecycleView
它有很多样板代码。在此处查看需要执行多少步骤RecyceView
:
创建 MainViewModel 并传入 MainContent
由于数据即将到来,您可以在将其作为参数传递给可组合函数时使用委托属性MainViewModel
创建它。by viewModels
MainActivity``MainContent()
MainActivity.kt
class MainActivity : ComponentActivity() {
val viewModel by viewModels<MainViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MainScreen(viewModel)
}
}
}
by viewModels
使用,以便在销毁和重新创建MainViewModel
实例时不会重新创建实例。MainActivity
请参阅此处的说明。
主屏幕.kt
@Composable
fun MainScreen(viewModel: MainViewModel) {
RecycleViewDemoTheme {
Scaffold(
topBar = { TopAppBar (title = {Text(stringResource(R.string.app_name))})
}
) {
MainContent(viewModel)
}
}
}
将 LiveData 转换为状态
在 Jetpack Compose 中,您需要将其转换为LiveData<T>
,State<T>
以便在数据更改或更新时能够正确重组。要转换它,请使用observeAsState()
LiveData
函数。
在此之前,您需要添加此库依赖项:
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
转换为 后State<T>
,您将值(即List<ItemData>
)作为ListContent()
可组合函数的参数。
@Composable
fun MainContent(viewModel: MainViewModel) {
val itemsState = viewModel.items.observeAsState()
itemsState.value?.let { items ->
ListContent(items)
}
}
实现 LazyColumn
由于RecycleView
item 原始实现填充了整个屏幕宽度并居中对齐,因此您需要执行相同的操作。这可以通过modifer
和horizontalAlignment
参数来完成LazyColumn
在最后一个参数LazyColumn
是Function Literal (Lambda Function) with Receiver。是LazyListScope
接收器。
要添加项目(即List<ItemData>
),请调用LazyListSciope.items()
可组合函数。要添加项目内容,您需要实现ShowItem()
仅显示文本的可组合功能。
为了匹配原始RecycleView
实现,我们将字体大小设置为34.sp
和FontWeight.Bold
。
代码如下所示:
@Composable
fun ListContent(items: List<ItemData>) {
LazyColumn (
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
items(items = items) { item ->
ShowItem(item)
}
}
}
@Composable
fun ShowItem(item: ItemData) {
Text(
text = item.id.toString(),
fontSize = 34.sp,
fontWeight = FontWeight.Bold
)
}
更新预览以包括 MainViewModel 创建
由于MainScreen()
接受MainViewModel
为参数,因此您需要创建它并传递它。
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
val viewModel = MainViewModel()
MainScreen(viewModel)
}
6. 完成
终于完成了!。RecycleView
该应用程序看起来像这样,这与基于视图的 UI 方法完全相同。
如果需要,您还可以通过将
MainContent()
可组合函数移出到一个更简洁的单独文件来重构代码。
参考
- 此处的转换差异:master vs compose 分支
- GitHub 存储库:Demo_SimpleRecycleView(撰写分支)
文章来源:https://vtsen.hashnode.dev/convert-recycleview-to-lazycolumn-jetpack-compose