«Круговая зависимость» может быть исправлена только путем удаления зависимости, которая вызывает эту проблему с одной из двух сторон.
Если вам нужен доступ к некоторым данным из кода библиотеки, вы можете реализовать интерфейс в библиотеке, который будет расширен некоторым классом в вашем проекте. После этого вы сможете использовать расширенный класс в своей библиотеке и методы доступа, определенные в интерфейсе .
Пример
Предположим, вам нужно получить ссылку на приложение контекст в вашей библиотеке. Вы должны создать интерфейс:
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
в свою библиотеку, как если бы это была инъекция зависимостей .
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 et c., Убедитесь, что вы позже удалили эта ссылка, когда объект будет уничтожен, чтобы избежать утечки памяти.
Пример того, как удалить ссылку на немного измененный код из предыдущего фрагмента кода:
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();
}
}
Обновление (10 августа 2020 г.): как использовать ContextAccessor?
Вот как вы можете использовать ContextAccessor
в своем библиотека:
class SomeLibraryClass {
private var mContextAccessor: ContextAccessor?
fun setContextAccessor(contextAccessor: ContextAccessor?) {
mContextAccessor = contextAccessor
}
fun someOtherMethod() {
mContextAccessor?.getAppContext()?.let { nonNullContext ->
// use nonNullContext here
}
}
}