Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 动态功能模块的第三方库无法访问资源_Android_Android Library_Dynamic Feature Module - Fatal编程技术网

Android 动态功能模块的第三方库无法访问资源

Android 动态功能模块的第三方库无法访问资源,android,android-library,dynamic-feature-module,Android,Android Library,Dynamic Feature Module,我有一个应用程序,它有一个动态功能模块。在动态特征模块中,有一个包含图像、输入字段的表单,还有一个访问另一个第三方库的Button 第三方库有一个活动和片段。在活动内部打开片段时,我收到以下错误,尽管活动的布局中有容器: 找不到片段SampleFragment{eed53f7(5e4c0693-09a2-4725-a6de-1df49dd818f0)id为0x7f080053(com.app.sample:id/container)的视图id=0x7f080053} 访问此第三方库中的drawa

我有一个应用程序,它有一个动态功能模块。在动态特征模块中,有一个包含图像、输入字段的表单,还有一个访问另一个第三方库的Button

第三方库有一个活动和片段。在活动内部打开片段时,我收到以下错误,尽管活动的布局中有容器:

找不到片段SampleFragment{eed53f7(5e4c0693-09a2-4725-a6de-1df49dd818f0)id为0x7f080053(com.app.sample:id/container)的视图id=0x7f080053}

访问此第三方库中的drawables时,出现以下错误:

java.lang.NoSuchFieldError:类Lcom.third.library/R$drawable中没有类型为I的静态字段ic_back;或其超类(声明'com.third.library.R$drawable'出现在/data/app/com.app.sample-QtC8XuamC1fHEVU4FUpWaA==/split_thirdparty.apk中)

在没有动态功能模块的应用程序中使用此库是很好的。
动态交付是一项相对较新的功能,因此它有很多局限性。其中一个限制是您不能以常规方式访问动态模块的代码和资源,因此它不能依赖于其他模块。目前,您可以通过反射访问动态模块,并通过公共库模块中的公共接口定义动态功能,并在运行时使用。它有它的性能缺点。使用R8可以将其最小化,但不能完全移除

虽然使用反射很容易出现错误,但我们可以使用-
AutoService
将其最小化。AutoService是一个注释处理器,它将扫描项目中使用
@AutoService
注释的类,对于它找到的任何类,它将自动为其生成一个服务定义文件

下面是一个小例子,说明如何做到这一点

// All feature definitions extend this interface, T is the dependencies that the feature requires
interface Feature<T> {
    fun getMainScreen(): Fragment
    fun getLaunchIntent(context: Context): Intent
    fun inject(dependencies: T)
}

interface VideoFeature : Feature<VideoFeature.Dependencies> {
    interface Dependencies {
        val okHttpClient: OkHttpClient
        val context: Context
        val handler: Handler
        val backgroundDispatcher: CoroutineDispatcher
    }
}

internal var videoComponent: VideoComponent? = null
    private set

@AutoService(VideoFeature::class)
class VideoFeatureImpl : VideoFeature {
    override fun getLaunchIntent(context: Context): Intent = Intent(context, VideoActivity::class.java)

    override fun getMainScreen(): Fragment = createVideoFragment()

    override fun inject(dependencies: VideoFeature.Dependencies) {
        if (videoComponent != null) {
            return
        }

        videoComponent = DaggerVideoComponent.factory()
                .create(dependencies, this)
    }
}
//所有功能定义都扩展了此接口,T是该功能所需的依赖项
接口特性{
fun getMainScreen():片段
趣味getLaunchIntent(上下文:上下文):Intent
乐趣注入(依赖项:T)
}
接口视频功能:功能{
接口依赖关系{
val okHttpClient:okHttpClient
val上下文:上下文
val处理程序:处理程序
val backgroundDispatcher:CoroutineDispatcher
}
}
内部var videoComponent:videoComponent?=无效的
专用设备
@自动服务(VideoFeature::class)
类VideoFeatureImpl:VideoFeature{
重写getLaunchIntent(上下文:context):Intent=Intent(上下文,VideoActivity::class.java)
重写getMainScreen():Fragment=createVideoFragment()
覆盖乐趣注入(依赖项:VideoFeature.dependencies){
if(videoComponent!=null){
返回
}
videoComponent=DaggerVideoComponent.factory()
.创建(依赖项,此)
}
}
并实际访问动态特性使用的代码


inline fun <reified T : Feature<D>, D> FeatureManager.getFeature(
        dependencies: D
): T? {
    return if (isFeatureInstalled<T>()) {
        val serviceIterator = ServiceLoader.load(
                T::class.java,
                T::class.java.classLoader
        ).iterator()

        if (serviceIterator.hasNext()) {
            val feature = serviceIterator.next()
            feature.apply { inject(dependencies) }
        } else {
            null
        }
    } else {
        null
    }
}

inline fun FeatureManager.getFeature(
依赖项:D
):T?{
如果(isFeatureInstalled()),则返回{
val serviceIterator=ServiceLoader.load(
T::class.java,
T::class.java.classLoader
).iterator()
if(serviceIterator.hasNext()){
val feature=serviceIterator.next()
feature.apply{inject(dependencies)}
}否则{
无效的
}
}否则{
无效的
}
}
摘自。还有更多的信息,所以我建议你检查一下

一般来说,我不建议使用动态特性作为依赖项,并相应地规划应用程序架构


希望有帮助。

通常,当在
活动2中未调用
SplitCompat.installActivity(this)
时,这将不起作用。虽然没有源代码,但您必须提取包并正确地重新打包,因为
活动2
(甚至整个库包)可能与DFM不兼容

为基础应用程序启用SplitCompat后,需要为应用程序在动态功能模块中下载的每个活动启用SplitCompat


下面是我的另一个示例,演示了如何通过反射进行访问。

对于资源,可以使用此代码部分

R.id.settings
将是:

getResources().getIdentifier("settings", "id", "com.library.package");

第三方库是否是一个开放库(例如在github上提供),以便我们可以复制?它是否仅用于
dynamic-feature-module1
App1
模块或
dynamic-feature-module1
级别的其他模块?可能值得一读,因为没有最少代码的错误消息相当抽象。