-
Author: xuweiyu
-
Date: 2021/10/16
*/
public class CommonLibrary {
public static String className = “CommonLibrary.java”;
}
将commonlibrary
工程打包成aar,上传至maven
[–>MyLibrary.java]
package com.example.mylibrary;
import com.example.commonlibrary.CommonLibrary;
/**
-
Author: xuweiyu
-
Date: 2021/10/16
*/
public class MyLibrary {
public static String clas
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
sName = “MyLibrary.java”;
public static String commonClassName = CommonLibrary.className;
}
[–>依赖配置]
dependencies {
implementation ‘com.xwy.test:commonlibrary:1.0.0’
}
mylibrary
工程会依赖commonlibrary
aar包
将mylibrary
工程打包成aar,上传至maven
此时就完成了业务组件对基础组件的依赖
app宿主工程如下:
package com.example.testactivitytask
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.example.mylibrary.MyLibrary
import com.example.testactivitytask.databinding.ActivitySecondBinding
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivitySecondBinding.inflate(layoutInflater)
setContentView(binding.root)
// 引用 library工程下的 MyLibrary
Log.e(“xwy–>”, “MyLibrary.className:${MyLibrary.className}”)
Log.e(“xwy–>”, “MyLibrary.commonClassName:${MyLibrary.commonClassName}”)
}
}
在app
工程中添加对mylibrary
的依赖
dependencies {
implementation ‘com.xwy.test:mylibrary:1.0.0’
…
}
运行结果
2021-10-16 13:53:11.019 29302-29302/com.example.testactivitytask E/xwy–>: MyLibrary.className:MyLibrary.java
2021-10-16 13:53:11.019 29302-29302/com.example.testactivitytask E/xwy–>: MyLibrary.commonClassName:CommonLibrary.java
一切正常
调试模式场景
在app
工程中添加对commonlibrary工程的源码依赖
dependencies {
implementation project(path: ‘:commonlibrary’)
// mylibrary aar 会传递依赖 commonlibrary aar
implementation ‘com.xwy.test:mylibrary:1.0.0’
…
}
修改commonlibrary工程代码
public class CommonLibrary {
public static String className = “CommonLibrary.java–>update”;
}
运行程序,会发现修改的源码没有生效。
执行gradlew build --refresh-dependencies
会显示如下的错误
Type com.example.commonlibrary.BuildConfig is defined multiple times:
/Users/xuweiyu/Work/TestActivityTask/commonlibrary/build/
.transforms/5da046d126b3df77c21768d16a3e3ca0/classes/classes.dex,
/Users/xuweiyu/Work/TestActivityTask/app/build/intermediates/external_libs_dex
/release/mergeExtDexRelease/classes.dex
解释一下这个错误,错误原因为dex文件合并的时候发现有多个com.example.commonlibrary.BuildConfig
文件。
原因为我们通过aar依赖和源码依赖,引入了两个相同文件。
3. 解决问题
既然问题出现的原因是引入了两份相同的代码,那么我们在编译的时候去除掉aar依赖不就可以了,一个被大众所熟知的方式就是在引入mylibrary
的时候去掉对commonlibrary
的依赖,那么我们可以这样做, 在app
工程依赖mylibrary
的时候采用如下方式:
dependencies {
implementation project(path: ‘:commonlibrary’)
// mylibrary aar 会传递依赖 commonlibrary aar, 利用exclude去除依赖
implementation (‘com.xwy.test:mylibrary:1.0.0’){
transitive = true
exclude group: ‘com.xwy.test’, module: ‘commonlibrary’
}
…
}
运行结果
2021-10-16 15:16:57.194 31535-31535/com.example.testactivitytask E/xwy–>: MyLibrary.className:MyLibrary.java
2021-10-16 15:16:57.194 31535-31535/com.example.testactivitytask E/xwy–>: MyLibrary.commonClassName:CommonLibrary.java–>update
可以看到修改的代码已经生效,问题可以解决。
弊端
-
配置文件修改侵入性高,需要修改依赖配置
-
如果有很多个业务组件都依赖了该基础组件,那么每一个业务组件都需要配置排除该基础组件的依赖
4. 终极解决方案
我们可以配置全局项目替换,一个不被大众所熟知的方式。 可以进行如下配置
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute module(“com.xwy.test:commonlibrary”) using project(":commonlibrary")
}
}
dependencies {
implementation(‘com.xwy.test:mylibrary:1.0.0’)
···
}
关于gradle
项目替换的语法说明,大家可以参考官方文档
Using dependency substitution rules
Dependency substitution rules work similarly to dependency resolve rules. In fact, many capabilities of dependency resolve rules can be implemented with dependency substitution rules. They allow project and module dependencies to be transparently substituted with specified replacements. Unlike dependency resolve rules, dependency substitution rules allow project and module dependencies to be substituted interchangeably.
Adding a dependency substitution rule to a configuration changes the timing of when that configuration is resolved. Instead of being resolved on first use, the configuration is instead resolved when the task graph is being constructed. This can have unexpected consequences if the configuration is being further modified during task execution, or if the configuration relies on modules that are published during execution of another task.