AndroidX迁移在英才App中实践

2,440 阅读4分钟

一、AndroidX是什么

鉴于Android support包版本依赖混乱,对实际开发不是很友好,经常出现依赖包重复或者项目本身与三方库的support包版本不一致等情况,Google 2018 IO 大会推出了 Android新的扩展库 AndroidX,用于替换原来的 Android扩展。替换完成后,只有包名和Maven工件名受到影响,原来的类名,方法名和字段名不会更改,原有的功能也不会改变,同时可以支持原有support库中一些没有的新特性。

二、为什么要做迁移

英才app计划接入flutter和招财猫团队开发的flutter kit工具库,然而接入flutter kit工具库后,重新编译运行后报错。错误信息如下:通过查看详细错误日志发现,是合并依赖组件中的AndroidManifest中存在相同属性,但是不同属性值造成的。按照日志提示添加在
标签里面加上:tools:replace="android:appComponentFactory"后重新编译运行依然报错,错误信息如下:


通过查看详细的编译日志发现,在support-compat-28.0.0.aar中的Androidman文件中该属性值为<Application android:appComponentFactory="android.support.v4.app.CoreComponentFactory" >;在core-1.1.0.aar中Androidman文件中该属性值为<Application android:appComponentFactory="androidx.core.app.CoreComponentFactory" >。查看zcm_flutter_kit sdk插件,发现在Android支持代码里引入了AndroidX依赖。

由于AndroidX库和Android Support库不能共存的原因,为了引入zcm flutter kit插件提高Flutter混合开发效率,并且以后可能会有越来越多的三方库支持AndroidX,因此有必要将英才项目中原有的support依赖改成AndroidX依赖。

三、如何迁移

1、环境准备

AndroidX的迁移要求在在AndroidStudio 3.2 或更高版本中执行,要求的targetSdkVersion版本为28(android9.0),classpath 'com.android.tools.build:gradle:3.2.0'要3.2.0或者更高。

2、修改gradle.properties

修改项目根目录gradle.properties文件,添加配置
android.useAndroidX=true //表示启用 androidx
android.enableJetifier=true //表示将依赖包迁移到androidx 。如果取值为false,表示不迁移依赖包到androidx,但在使用依赖包中的内容时可能会出现问题,如果项目中没有使用任何三方依赖,可以设置为false。

3、启动一键迁移

在AS中执行Refactor->Migrate to AndroidX

迁移后执行 Flie -> Invalidate Caches /Restart 一下,确保依赖中的缓存文件都已更新。

四、修改项目代码

AS中虽然提供了一键迁移插件工具,但是替换效果并不好。因此,在使用一键迁移完成后,还需要手动修改项目中出错的地方。

1、库依赖

由于英才项目是组件化开发结构,因此在引入依赖的时候,在根目录下创建了config.gradle文件,把依赖库地址单独放在config.gradle里。其优点在于,各模块需要引用相关库的时候,直接取config.gradle中相对应的库名字,从而避免各模块中依赖库版本不一致的问题。

但是AndroidX一键迁移操作并不能识别这种依赖方式,因此没有完成自动修改。需要手动将support依赖如下

"support-v4"         : "com.android.support:support-v4:${dependVersion.support}",
"appcompat-v7"        : "com.android.support:appcompat-v7:${dependVersion.support}",
"design"              : "com.android.support:design:${dependVersion.support}",
"recyclerview"        : "com.android.support:recyclerview-v7:${dependVersion.support}",
"cardview"            : "com.android.support:cardview-v7:${dependVersion.support}",
"annotations"         : "com.android.support:support-annotations:${dependVersion.support}",
"constraint-layout"   : "com.android.support.constraint:constraint-layout:1.0.2",

修改为

"support-v4"          : "androidx.legacy:legacy-support-v4:1.0.0",
"appcompat-v7"        : "androidx.appcompat:appcompat:1.0.2",
"design"              : "com.google.android.material:material:1.1.0-alpha09",
"recyclerview"        : "androidx.recyclerview:recyclerview:1.0.0",
"cardview"            : "androidx.cardview:cardview:1.0.0",
"annotations"         : "androidx.annotation:annotation:1.0.0",
"constraint-layout"   : "androidx.constraintlayout:constraintlayout:1.1.3",


2、Activity/Fragment等Java文件和XML布局文件改动

Activity/Fragment/XML(包括涉及到使用support包的工具类等),原来引用support包中的类,在Migrate后并不能完全对应,会有很多错误,所以需要改成对应的androidX中的类引用。如果挨个删掉原有的引用后,再重新导入正确的引用包,工作量会非常繁重。因此,可以使用全局替换: Edit ->Find -> Replace in path 。

整理出来常见的对应关系如下:

android.support.annotation.Nullable                  androidx.annotation.Nullable
android.support.annotation.NonNull                   androidx.annotation.NonNull;
androidx.appcompat.widget.GridLayoutManager          androidx.recyclerview.widget.GridLayoutManager
androidx.appcompat.widget.RecyclerView               androidx.recyclerview.widget.RecyclerView;
androidx.appcompat.widget.LinearLayoutManager        androidx.recyclerview.widget.LinearLayoutManager
androidx.appcompat.widget.LinearSmoothScroller       androidx.recyclerview.widget.LinearSmoothScroller
androidx.appcompat.widget.OrientationHelper          androidx.recyclerview.widget.OrientationHelper
androidx.appcompat.widget.SnapHelper                 androidx.recyclerview.widget.SnapHelper
androidx.core.app.FragmentTransaction                androidx.fragment.app.FragmentTransaction
androidx.core.app.Fragment;                          androidx.fragment.app.Fragment;
androidx.core.app.FragmentManager                    androidx.fragment.app.FragmentManager;
androidx.core.app.FragmentStatePagerAdapter          androidx.fragment.app.FragmentStatePagerAdapter
androidx.core.view.ViewPager                         androidx.viewpager.widget.ViewPager
androidx.core.app.FragmentActivity                   androidx.fragment.app.FragmentActivity
android.support.annotation.ColorInt                  androidx.annotation.ColorInt
android.support.annotation.ColorRes                  androidx.annotation.ColorRes
android.support.annotation.FloatRange                androidx.annotation.FloatRange
android.support.annotation.AttrRes                   androidx.annotation.AttrRes
android.support.design.widget.AppBarLayout           com.google.android.material.appbar.AppBarLayout
android.support.design.widget.CoordinatorLayout      androidx.coordinatorlayout.widget.CoordinatorLayout


布局XML文件里面,也不会自动替换,需要手动替换

<androidx.constraintlayout.ConstraintLayout/>             <androidx.constraintlayout.widget.ConstraintLayout/>
<android.support.design.widget.CollapsingToolbarLayout/>  <com.google.android.material.appbar.CollapsingToolbarLayout/>
<android.support.v7.widget.Toolbar/>                      <androidx.appcompat.widget.Toolbar/>
<android.support.v4.view.ViewPager/>                      <androidx.viewpager.widget.ViewPager/>
<android.support.v7.widget.RecyclerView/>                 <androidx.recyclerview.widget.RecyclerView/>


3、查漏补缺

1)全局替换也可能有少数遗漏或者错误的情况,可以再全局Find in Path ,使用support关键字全局查找,再做替换

2) 替换完成后,进行Rebuild,如果有错误,编译失败。再进行手动修改,经过几次编译尝试后,最终达到编译成功,表示项目代码修改完成。


五、其他问题

1、注解处理器冲突

项目中使用的butterknife不支持androidx,导致引用Butterknife的文件都报错。10.1.0版本已经做了兼容,因此将项目中的

"butterknife"         : "com.jakewharton:butterknife:8.8.1",
"butterknife-compiler": "com.jakewharton:butterknife-compiler:8.8.1",

升级到10.1.0

"butterknife"         : "com.jakewharton:butterknife:10.1.0",
"butterknife-compiler": "com.jakewharton:butterknife-compiler:10.1.0",

2、android dependency 'androidx.core:core' has different version for the compile (1.0.0) and runtime (1.0.1) classpath.You should manually set the same version via DependencyResolution 编译报错

出现这个问题是由于引入的依赖库版本与编译环境版本不一致造成的,在工程根目录build.gradle文件添加配置即可解决,如下

subprojects {
    project.configurations.all {
        //AndroidX版本不同解决方案
        resolutionStrategy.eachDependency { details ->
            if (details.requested.group == 'androidx.core') {
                details.useVersion '1.1.0'//这个版本号设置为你想要的版本
            }
        }
    }
}

六、混淆配置

修改前的混淆文件是针对support库做的混淆配置,在完成迁移后,需要添加对AndroidX的混淆配置

-keep class com.google.android.material.** {*;}
-keep class androidx.** {*;}
-keep public class * extends androidx.**
-keep interface androidx.** {*;}
-dontwarn com.google.android.material.**
-dontnote com.google.android.material.**
-dontwarn androidx.**


参考文档:

developer.android.google.cn/jetpack/and…

developer.android.google.cn/jetpack/and…

developer.android.google.cn/jetpack/and…

www.jianshu.com/p/499e645ad…