“循环依赖”只能通过删除在两侧之一上导致此问题的依赖性来修复。
如果您需要从库代码中访问某些数据,您可以在库中实现一个接口,该接口将由您项目中的某个类扩展。然后,您将能够使用库中的扩展类和接口中定义的访问方法。
示例
假设您需要在库中获取对应用程序上下文的引用。你应该创建一个接口:
interface ContextAccessor {
// Marking it as optional just in case
// you will not be able to get a context
// from an object that implemented ContextAccessor
fun getApplicationContext(): Application?
}
因为您将该库作为依赖项添加到项目中,所以您可以访问ContextAccessor。用这个接口扩展一些类并实现getApplicationContext 方法。假设您想扩展一些Activity。
class MyActivity: Activity, ContextAccessor {
... other code here
override fun getApplicationContext(): Application? = application
}
现在,在您的 MyActivity 类中,您可以将 ContextAccessor 设置到您的库中,就好像它是 dependency injection。
class MyActivity: Activity, ContextAccessor {
... other code here
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val someLibraryClassInstance = SomeLibraryClass()
someLibraryClassInstance.setContextAccessor(this)
// OR -> `someLibraryClassInstance.contextAccessor = this`
}
}
警告:当您保存对任何 Android 组件(尤其是 Activity、Fragment、Dialog 等)的引用时,请确保稍后在对象将要被销毁时删除此引用避免内存泄漏。
如何从之前的代码sn-p中删除对一点点修改代码的引用:
class MyActivity: Activity, ContextAccessor {
... other code here
private val someLibraryClassInstance = SomeLibraryClass()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ContextAccessor reference is set to some library class
someLibraryClassInstance.setContextAccessor(this)
}
override fun onDestroy() {
super.onDestroy()
// Super important!
someLibraryClassInstance.setContextAccessor(null)
// OR create some method like `someLibraryClassInstance.removeContextAccessor(this)`
}
}
Java 中的相同类
interface ContextAccessor {
// Marking it as optional just in case
// you will not be able to get a context
// from an object that implemented ContextAccessor
Application getApplicationContext();
}
public class MyActivity extends Activity implements MyActivity.ContextAccessor {
private SomeLibraryClass someLibraryClassInstance = SomeLibraryClass();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ContextAccessor reference is set to some library class
someLibraryClassInstance.setContextAccessor(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
// Super important!
someLibraryClassInstance.setContextAccessor(null);
// OR create some method like `someLibraryClassInstance.removeContextAccessor(this)`
}
@Override
public Application getApplicationContext() {
return super.getApplication();
}
}
更新(2020 年 8 月 10 日):如何使用 ContextAccessor?
您可以在库中使用ContextAccessor:
class SomeLibraryClass {
private var mContextAccessor: ContextAccessor?
fun setContextAccessor(contextAccessor: ContextAccessor?) {
mContextAccessor = contextAccessor
}
fun someOtherMethod() {
mContextAccessor?.getAppContext()?.let { nonNullContext ->
// use nonNullContext here
}
}
}