Compose多平台桌面项目动态加载Jar遇MissingResourceException问题
Compose Multiplatform桌面端动态加载Jar资源缺失问题解决
核心原因
Compose Resources桌面端默认使用调用类的ClassLoader加载资源,但动态加载的Jar使用自定义URLClassLoader,默认的ResourceReader并未使用这个加载器查找Jar内的composeResources目录,导致资源路径匹配但无法读取。
具体解决步骤
1. 自定义适配动态ClassLoader的ResourceReader
在主项目或功能模块中添加自定义ResourceReader,让它能使用动态加载的ClassLoader读取资源:
import org.jetbrains.compose.resources.ResourceReader import java.io.InputStream class DynamicResourceReader(private val classLoader: ClassLoader) : ResourceReader { override fun getResourceAsStream(path: String): InputStream? { // 直接使用传入的ClassLoader查找资源 return classLoader.getResourceAsStream(path) } }
2. 动态加载Jar时替换全局ResourceReader
修改动态加载代码,在实例化PluginApp后,替换Compose的全局ResourceReader为自定义实现,传入对应的URLClassLoader:
val url = File(pluginJarPath).toURI().toURL() val classLoader = URLClassLoader(arrayOf(url), this.javaClass.classLoader) return try { val pluginClass = classLoader.loadClass("com.sample.feature.ComposeApp") // 替换全局ResourceReader,让Compose使用动态加载的ClassLoader读取资源 org.jetbrains.compose.resources.ResourceReader_desktopKt.setPlatformResourceReader( DynamicResourceReader(classLoader) ) pluginClass.getDeclaredConstructor().newInstance() as PluginApp } catch (e: Exception) { e.printStackTrace() null }
注:如果需要加载多个插件,需在切换插件时重新设置对应插件的ResourceReader,保证资源隔离。
3. 确保Jar打包完整包含资源
检查Jar打包任务,明确包含composeResources目录(避免资源遗漏):
val jarVersion = 1.0.0 tasks.register<Jar>("jars") { archiveBaseName.set("feature") archiveVersion.set(jarVersion) manifest { attributes["Implementation-Title"] = "Feature Plugin App" attributes["Implementation-Version"] = jarVersion } duplicatesStrategy = DuplicatesStrategy.EXCLUDE // 包含jvmMain的所有输出(类文件+资源文件) from(sourceSets["jvmMain"].output) // 显式确认composeResources目录被打包 from(sourceSets["jvmMain"].resources) { include("composeResources/**") } }
4. 可选:插件卸载时恢复原有ResourceReader
如果应用支持插件卸载,记得恢复原来的ResourceReader:
// 加载插件前保存原有ResourceReader val originalReader = org.jetbrains.compose.resources.ResourceReader_desktopKt.getPlatformResourceReader() // 加载插件时替换为自定义Reader // ... // 卸载插件时恢复原有Reader org.jetbrains.compose.resources.ResourceReader_desktopKt.setPlatformResourceReader(originalReader)
验证
完成上述修改后,重新打包功能模块Jar并动态加载,导航到功能模块页面即可正常读取资源,不再抛出MissingResourceException。
内容的提问来源于stack exchange,提问作者Alex Shapkin
相关产品推荐
相关产品推荐

