theme: smartblue
背景
最近我司正在做关于
kotlin
和
jetpack
版本升级的工作。我这次就被分派到了
jetpack
的升级工作了,这次目标版本就是谷歌最新的release版本。
本来以为是个非常简单的工作,就是把所有版本都升上去就搞定了吗!这不是分分钟就能搞定的事情吗。
最后发现竟然这么多坑点的吗。
今天的大部分文章内容我都在路由的那个项目里面,完成了简单的代码以及demo,有兴趣的可以了解下。 传送门
全是坑啊
首先我们根据官方文档对上述版本进行升级。我们在升级
androidx.fragment:fragment-ktx
和
androidx.activity:activity-ktx
发现奇怪的问题,因为他们的
pom
使用
lifecycle-runtime
的版本,所以我们必须同时对
lifecycle
也进行对应的升级。
然后我就裂开了,官方移除了
androidx.lifecycle:lifecycle-extensions
这个仓库,这个库被变更成了
androidx.lifecycle:lifecycle-process
。
这个时候我们发现了一个鬼畜的问题,因为一些在主工程的项目也有依赖了这个库,那么就会导致依赖被传递到主工程内。但是如果像打地鼠一样一个个把这个仓移除,万一漏掉了就会非常尴尬。
移除所有依赖
这次就要讲讲茴字的三种写法了 !
其实可以在
application
目录的
build.gradle
下面添加如下groovy。可以保证在打包的时候剔除这部分依赖。
configurations {
all*.exclude group: 'androidx.lifecycle', module: 'lifecycle-extensions'
}
或者你可以考虑下用我的另外一种写法,通过根目录的
build.gradle
剔除项目内所有
project
所有的子模块。
这个方式的好处就是因为所有的子模块的都剔除了对应的依赖,这样后续就不会直接使用到依赖的代码了。
allprojects {
configurations.all { Configuration c ->
if (c.state == Configuration.State.UNRESOLVED) {
exclude group: 'androidx.lifecycle', module: "lifecycle-extensions"
}
通过
allproject+configuration
的方式,我们就可以这部分调用exclude的方式给项目统一移除特定的依赖了。
当然还有另外一种方式了,就是通过策略,然后将一部分依赖进行一次替换,A换成B就是这样。
allprojects {
configurations.all { Configuration c ->
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'androidx.lifecycle' && details.requested.name == 'lifecycle-extensions') {
details.useTarget group: 'androidx.lifecycle', name: 'lifecycle-process'
}
。 这部分功能吧,其实还是有很意思的。你能对于gradle的一个重要的
configuration
有一个更深入的了解
ViewModelProviders被移除了
我们碰到的第二个问题就是在最新版本中
ViewModelProviders
被移除了,这我的天啊,要了老命了。
这部分其实也还是比较简单的,因为我们上面剔除了旧的依赖,所以我们的项目内项目内其实已经没有了
ViewModelProviders
的代码了。第一个版本我们尽量避免大面积改造,所以我们只要同包名下拷贝一个类似的
ViewModelProviders
类就行了。
但是我们正常只需要几个
of
方法就好了。
package androidx.lifecycle
@Deprecated("ViewModelProviders adapter not support any more")
object ViewModelProviders {
@MainThread
@JvmStatic
fun of(activity: FragmentActivity): ViewModelProvider {
return ViewModelProvider(activity)
@MainThread
@JvmStatic
fun of(activity: FragmentActivity, factory: ViewModelProvider.Factory?): ViewModelProvider {
return if (factory == null) {
ViewModelProvider(activity)
} else {
ViewModelProvider(activity, factory)
@MainThread
@JvmStatic
fun of(fragment: Fragment): ViewModelProvider {
return ViewModelProvider(fragment)
@MainThread
@JvmStatic
fun of(fragment: Fragment, factory: ViewModelProvider.Factory?): ViewModelProvider {
return if (factory == null) {
ViewModelProvider(fragment)
} else {
ViewModelProvider(fragment, factory)
}
所以我们大概只要生成要给这样类就行了,可以解决第一期的替换问题了。但是过期的类也就没必要一直这么维持下去了,所以我们后续打算二期通过静态检查(lint)的方式,让业务进行改动。
jvm 1.8也挂了?
这次在我们升级的过程中,我们发现了有一部分仓库直接用了
androidx.activity:activity-ktx
和
androidx.fragment:fragment-ktx
。他们获取到
ViewModel
的形式是通过fragment或者activity的拓展函数,
viewModels
委托来完成的。
但是由于升级
SDK
,其中的
noinline
方法内联由于需要使用到
kotlin jvm 1.8
来进行编译,所以就出现了无法编译的问题,解决方案也比较简单,就是通过在
Module
下的
build.gradle
设置如下代码。
kotlinOptions {
jvmTarget = "1.8"
}
但是有没有一个比较通用的方法可以直接把项目内所有的模块都设置成
jvmTarget
的方法呢?
allprojects {