Доступ к основному проекту из модуля в Android Studio? - PullRequest
7 голосов
/ 01 августа 2020

Я использую эту библиотеку , которую я установил локально как модуль. Я могу получить к нему доступ через свой основной проект, но не могу сделать наоборот. Например, получить доступ к переменной в моем основном проекте из этой библиотеки ...

Я попытался добавить эту строку в библиотеку build.gradle:

    implementation project(':app')

Но я получаю эту странную ошибку:

Circular dependency between the following tasks:
:placepicker:generateDebugRFile
\--- :placepicker:generateDebugRFile (*)
    
(*) - details omitted (listed previously)

Как это исправить? Мой проект находится в Java, а моя библиотека - в Kotlin

Ответы [ 2 ]

3 голосов
/ 01 августа 2020

«Круговая зависимость» может быть исправлена ​​только путем удаления зависимости, которая вызывает эту проблему с одной из двух сторон.

Если вам нужен доступ к некоторым данным из кода библиотеки, вы можете реализовать интерфейс в библиотеке, который будет расширен некоторым классом в вашем проекте. После этого вы сможете использовать расширенный класс в своей библиотеке и методы доступа, определенные в интерфейсе .

Пример

Предположим, вам нужно получить ссылку на приложение контекст в вашей библиотеке. Вы должны создать интерфейс:

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
        }
    }
}
0 голосов
/ 12 августа 2020

Вы можете переместить свои классы, которые использовались в обоих модулях, в другой (третий модуль) и использовать его в своем модуле приложения и другом модуле, который вам нужен.

в модуле приложения: проект реализации (": третий")

во втором модуле: проект внедрения (": третий")

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...