【发布时间】:2015-06-20 08:38:20
【问题描述】:
所以我想构建一个可扩展的 android 应用程序,开发人员可以在其中添加“CustomDevice”类,主程序将自动运行它们而无需编辑现有代码。
我已经阅读了有关服务提供者接口的信息,并认为这是一个很好的解决方法。
因此我对其进行了测试并创建了一个名为“ICustomDevice”的接口,自定义设备类有望实现该接口。
我创建了一个名为“DummyDevice”的类,它实现了 ICustomDevice。
DummyDevice 和 ICustomDevice 都在同一个包“CustomDevicePackage”中。
所以在我的主程序中,我运行以下命令。
ServiceLoader<ICustomDevice> loader = ServiceLoader.load(ICustomDevice.class);
Iterator<ICustomDevice> devices = loader.iterator();
System.out.println("Does it have devices? " + devices.hasNext());
它总是返回 false,这意味着它没有找到 'DummyDevice'
在我的 Eclipse 项目中,我在“src”中创建了一个名为 META-INF 的文件夹,并在其下创建了一个名为“services”的子文件夹。
“服务”有一个名为“CustomDevicePackage.ICustomDevice”的文件,其中包含一行内容“CustomDevicePackage.DummyDevice”。
我做得对吗?我看到的每个关于 SPI 的例子都是关于加载 JARS。 我没有加载 JAR,我正在尝试在同一个项目中运行一个类。此方法是否仅适用于加载 JAR?我希望我的程序支持加载本地子类和外部 JAR。
【问题讨论】:
-
引用Dianne Hackborn,一位从事 Android 工作的关键 Google 工程师:“ServiceLoader 是来自 Java 语言的东西,与 Android 并不真正相关。我建议不要使用它。”
-
引用对我们这些在 Java 世界中使用 ServiceLoader 并尝试移植到 Android 的人没有帮助(无需重写大量代码)。我检查了 apk,正确的文件位于 META-INF/services 下(在我的情况下,没有像作者一样的 jars)。任何帮助解决将不胜感激。
-
看来 getResource 正在“META-INF/services”文件夹上完成,这就是问题所在。 ClassLoader.getResource() 返回 null。我没有看到一个简单的方法。
-
对高速报价感到抱歉,但有更多信息:ServiceLoader 正在使用 getResources(复数)来获取所有服务的 URL。 URL 是一个 jar:file "protocol" 并得到异常:"Provider "jar" not installed"。由于Android世界没有jar,所以没有用于URL解析的jar提供者。
-
URL.openStream() 有效!使用类的类加载器、Thead 的 contextClassLoader 和 ClassLoader.getSystemClassLoader() 进行测试(如果加载时 ClassLoader 为空,则使用:只有 getSystemClassLoader() 无法返回任何文件。要检查使用 load(class, classloader) 强制使用非系统加载器。
标签: android meta-inf serviceloader