将Compose迁移到现有项目
# 升级AndroidStudio
你可以升级AndroidStudio为最新版,直接去AndroidStudio官网 (opens new window)更新AndroidStudio即可。
# 升级gradle
你需要升级你的gradle为7.0及以上,如下:
buildscript {
...
dependencies {
classpath "com.android.tools.build:gradle:7.0.0"
...
}
}
2
3
4
5
6
7
这一步可能遇到很多问题,请移步到后面的问题以及解决。
# 升级kotlin版本
接着,你需要升级你的kotlin版本为1.5.21及以上,如下:
plugins {
id 'org.jetbrains.kotlin:android' version '1.5.21'
}
2
3
# 开启Compose
接着,你需要将应用的最低API版本设置为21及以上,并在build.gradle中启用Compose,还需要指定kotlin编译器插件版本,如下:
android {
defaultConfig {
...
minSdkVersion 21 // 最低版本为21
}
buildFeatures {
// 为当前module启用 compose
compose true
}
...
// java和kotlin编译版本都指定为1.8
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
// 指定编译版本
composeOptions {
kotlinCompilerExtensionVersion '1.0.1'
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
并且,你需要指定项目的JDK版本为JDK11及以上。 AndroidStudio -> 设置 -> Gradle -> Gradle JDK -> 选择JDK11及以上。
# 添加依赖
接着,你需要在开启compose的module中的build.gradle中添加compose使用的依赖,比如我自己的项目中添加有如下依赖:
compose_version = '1.0.1'
// 基础UI框架
implementation "androidx.compose.ui:ui:$compose_version"
// Material风格布局
implementation "androidx.compose.material:material:$compose_version"
// Compose扩展Activity
implementation 'androidx.activity:activity-compose:1.3.0-alpha06'
// UI测试
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
// UI工具包
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
// Material风格图标
implementation("androidx.compose.material:material-icons-core:$compose_version")
implementation("androidx.compose.material:material-icons-extended:$compose_version")
// 图片加载框架
implementation 'io.coil-kt:coil-compose:1.3.0'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
这些依赖不唯一,可以根据项目的需要添加。
# Compose和原生View的互调
# Android原生View使用ComposeView
比如我用Compose写了个界面,要在原来的xml布局中使用它,可以这样:
- 在xml布局中添加androidx.compose.ui.ComposeView,然后findViewById(id)出来,然后使用composeView.setContent(@Composable)即可。
- 直接在代码中创建出ComposeView,然后使用composeView.setContent(@Composable)
比如第一种方式:
我们先在xml文件中添加androidx.compose.ui.ComposeView
<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
2
3
4
然后在代码中使用:
// 定义一个Compose风格的View
@Composable
fun TextView() {
Text(text = "this is a compose TextView")
}
// 使用
val composeView: ComposeView = findViewById(R.id.compose_view)
composeView.setContent { TextView() }
2
3
4
5
6
7
8
9
10
# ComposeView使用Android原生View
在@Composable内使用: androidx.compose.ui.viewinterop.AndroidView,然后在factory里面返回原生View即可。如下:
@Composable
fun TextView() {
Text(text = "this is a compose TextView")
// 使用androidx.compose.ui.viewinterop.AndroidView
AndroidView(
// 需要提供一个factory来返回我们要使用的Android原生View,这里我们返回一个原生的ImageView
factory = { context ->
ImageView(context)
},
// modifier,可以不提供
modifier = Modifier.padding(20.dp),
// update,每次compose重组会调用到这里,可以不提供
update = { imageView ->
Log.d("Compsose", "$imageView has update")
})
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
AndroidView的函数原型如下:
@Composable
fun <T : View> AndroidView(
factory: (Context) -> T, // 返回原生View
modifier: Modifier = Modifier, // 修饰符
update: (T) -> Unit = NoOpUpdate // 每次界面重组(更新)调用
)
2
3
4
5
6
# 问题以及解决
我们遇到的大部分问题都是兼容性问题,而且集中在升级gradle到7.0这一步,再次吐槽下gradle!
- 1 所有使用compile 'xxxx'需要替换为api/implementation 'xxxx'。
- 2 gradle7.0不再支持非http的依赖,所以原有的http仓库的依赖,需要替换为https依赖,比如:
maven {
url 'http://dl.bintray.com/umsdk/release' // http仓库不安全
}
2
3
就要替换为
maven {
url 'https://dl.bintray.com/umsdk/release' // 替换为https类型的仓库
}
2
3
- 3 一些插件会失效,所以要 去这些插件的官网 或者 gradle官网 查看更新日志 来找到对应的替换方案,比如: 比如 apply plugin 'maven',需要替换为 apply plugin 'maven-publish'
- 4 gradle的一些语法有更新,需要查看更新日志来进行更新,比如: 使用maven进行仓库发布的api更新了,就需要查看官网进行修改。
- 5 如果你的项目是混合开发,比如rn或者flutter,就需要检测这些项目并且做相应更新(很蛋疼!)。
# 最后
迁移Compose到现有项目,需要耐住脾气和性子,一点一点来,不然很容易火大,而且要自底向上迁移,尽量缩小影响范围。
最后想吐槽一下,Google更新的真频繁!!!