从Android Studio中的模块访问主项目?

Ban*_*ndy 6 java android kotlin

我正在使用我在本地安装的这个库作为模块。我可以通过我的主项目访问它,但我不能做相反的事情。例如,从这个库访问我的主项目中的一个变量......

我尝试在库中添加这一行build.gradle

    implementation project(':app')
Run Code Online (Sandbox Code Playgroud)

但我收到了这个奇怪的错误:

Circular dependency between the following tasks:
:placepicker:generateDebugRFile
\--- :placepicker:generateDebugRFile (*)
    
(*) - details omitted (listed previously)
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个问题?我的项目在 Java 中,我的库在 Kotlin 中

Jen*_*anu 3

“循环依赖”只能通过删除导致两侧之一出现此问题的依赖来修复。

如果您需要从库代码访问某些数据,您可以在库中实现一个接口,该接口将由项目中的某个类扩展。然后您将能够在库中使用扩展类并访问接口中定义的方法

例子

假设您需要获取对库中应用程序上下文的引用。您应该创建一个接口:

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?
}
Run Code Online (Sandbox Code Playgroud)

因为您将该库添加为项目中的依赖项,所以您可以访问ContextAccessor. 使用此接口扩展某个类并实现该getApplicationContext方法。假设您想延长一些Activity.

class MyActivity: Activity, ContextAccessor {
    ... other code here

    override fun getApplicationContext(): Application? = application
}
Run Code Online (Sandbox Code Playgroud)

现在,在您的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`
    }
}
Run Code Online (Sandbox Code Playgroud)

警告当您保存对任何 Android 组件(尤其是 Activity、Fragment、Dialog 等)的引用时,请确保稍后在对象将要被销毁时删除此引用,以避免内存泄漏。

如何从前面的代码片段中删除对稍微修改过的代码的引用的示例:

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)`
    }
}
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)
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();
    }
}
Run Code Online (Sandbox Code Playgroud)

更新(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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)