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

huangapple go评论85阅读模式
英文:

Access main project from module in Android Studio?

问题

我正在使用这个库,我已经将其作为模块本地安装。我可以通过我的主项目访问它,但反之则不行。例如,无法从这个库中访问我的主项目中的变量...

我尝试在库的build.gradle中添加以下行:

    implementation project(':app')

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

以下任务之间存在循环依赖关系:
:placepicker:generateDebugRFile
\--- :placepicker:generateDebugRFile (*)
    
(*) - 详细信息已省略(在先前列出)

我该如何解决这个问题?我的项目是用Java编写的,我的库是用Kotlin编写的。

英文:

I am using this library which I have installed locally as a module. I'm able to access it via my main project, but I'm not able to do the opposite. For example, access a variable in my main project from this library...

I tried adding this line in the library's build.gradle:

    implementation project(':app')

But I get this weird error:

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

How can I fix this? My project is in Java and my library is in Kotlin

答案1

得分: 3

"Circular dependency" 只能通过在两者之一上移除导致此问题的依赖关系来解决。

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

示例

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

interface ContextAccessor {
    // 将其标记为可选,以防万一
    // 无法从实现ContextAccessor的对象中获取上下文
    fun getApplicationContext(): Application?
}

因为您将库添加为项目的依赖项,所以您可以访问ContextAccessor。扩展某个类以实现这个接口并实现getApplicationContext方法。假设您想扩展某个Activity

class MyActivity: Activity, ContextAccessor {
    ...其他代码在这里

    override fun getApplicationContext(): Application? = application
}

现在,在MyActivity类内部,您可以将ContextAccessor设置到库中,就像它是依赖注入一样。

class MyActivity: Activity, ContextAccessor {
    ...其他代码在这里
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val someLibraryClassInstance = SomeLibraryClass()
        someLibraryClassInstance.setContextAccessor(this)
        // 或者 -> `someLibraryClassInstance.contextAccessor = this`
    }
}

警告当您保存对任何Android组件的引用时,特别是Activity、Fragment、Dialog等等,请确保在对象即将销毁时删除此引用,以避免内存泄漏。

从上一个代码段中稍微修改的代码的删除引用示例:

class MyActivity: Activity, ContextAccessor {
    ...其他代码在这里 

    private val someLibraryClassInstance = SomeLibraryClass()   
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
         
        // 将ContextAccessor引用设置给某个库类
        someLibraryClassInstance.setContextAccessor(this)
    }

    override fun onDestroy() {
        super.onDestroy()

        // 非常重要!
        someLibraryClassInstance.setContextAccessor(null)
        // 或者创建一些方法,比如 `someLibraryClassInstance.removeContextAccessor(this)`
    }
}

在Java中相同的类

interface ContextAccessor {
    // 将其标记为可选,以防万一
    // 无法从实现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引用设置给某个库类
        someLibraryClassInstance.setContextAccessor(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 非常重要!
        someLibraryClassInstance.setContextAccessor(null);
        // 或者创建一些方法,比如 `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?.getApplicationContext()?.let { nonNullContext ->
            // 在这里使用非空的上下文
        }
    }
}
英文:

"Circular dependency" can be fixed only by removing dependency that causes this issue on one of two sides.

If you need to access some data from the library code you can implement an interface in a library that will be extended by some class in your project. Then you will be able to use extended class in your library and access methods defined in the interface.

Example

Let's imagine you need to get a reference to the application context within your library. You should create an interface:

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?
}

Because you added the library as a dependency in your project you have access to ContextAccessor. Extend some class with this interface and implement the getApplicationContext method. Let's say you want to extend some Activity.

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

    override fun getApplicationContext(): Application? = application
}

Now from within your MyActivity class, you can set ContextAccessor into your library as if it was 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`
    }
}

WARNING: when you save a reference to any Android component, especially Activity, Fragment, Dialog etc., make sure you later remove this reference when the object is going to be destroyed to avoid memory leaks.

An example of how to remove a reference on a little bit modified code from the previous code snippet:

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)`
    }
}

Same classes in 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();
    }
}

Update (10 aug 2020): how to use ContextAccessor?

Here is how you can use ContextAccessor in your library:

class SomeLibraryClass {
    private var mContextAccessor: ContextAccessor?

    fun setContextAccessor(contextAccessor: ContextAccessor?) {
        mContextAccessor = contextAccessor
    }
    
    fun someOtherMethod() {
        mContextAccessor?.getAppContext()?.let { nonNullContext ->
            // use nonNullContext here
        }
    }
}

答案2

得分: 2

在应用模块中:
implementation project(":third")

在第二模块中:
implementation project(":third")

英文:

You can move your classes that used in both modules to another (third module) and use it in your app module and another module you want.

in app module:
implementation project(":third")

in second module:
implementation project(":third")

huangapple
  • 本文由 发表于 2020年8月1日 19:25:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/63204657.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定