【发布时间】:2018-02-19 21:29:02
【问题描述】:
我有一个大型 Android 应用,它需要根据操作系统版本、制造商和许多其他因素运行不同的代码。但是,此应用程序必须是单个 APK。它需要在运行时足够聪明才能确定要使用的代码。到目前为止,我们一直在使用 Guice,但性能问题导致我们考虑迁移到 Dagger。但是,我无法确定我们是否可以实现相同的用例。
我们的主要目标是在启动时运行一些代码以提供兼容模块的列表。然后将该列表传递给 Dagger 以连接所有内容。
这是我们要迁移的 Guice 当前实现的一些伪代码
import com.google.inject.AbstractModule;
@Feature("Wifi")
public class WifiDefaultModule extends AbstractModule {
@Override
protected void configure() {
bind(WifiManager.class).to(WifiDefaultManager.class);
bind(WifiProcessor.class).to(WifiDefaultProcessor.class);
}
}
@Feature("Wifi")
@CompatibleWithMinOS(OS > 4.4)
class Wifi44Module extends WifiDefaultModule {
@Override
protected void configure() {
bind(WifiManager.class).to(Wifi44Manager.class);
bindProcessor();
}
@Override
protected void bindProcessor() {
(WifiProcessor.class).to(Wifi44Processor.class);
}
}
@Feature("Wifi")
@CompatibleWithMinOS(OS > 4.4)
@CompatibleWithManufacturer("samsung")
class WifiSamsung44Module extends Wifi44Module {
@Override
protected void bindProcessor() {
bind(WifiProcessor.class).to(SamsungWifiProcessor.class);
}
@Feature("NFC")
public class NfcDefaultModule extends AbstractModule {
@Override
protected void configure() {
bind(NfcManager.class).to(NfcDefaultManager.class);
}
}
@Feature("NFC")
@CompatibleWithMinOS(OS > 6.0)
class Nfc60Module extends NfcDefaultModule {
@Override
protected void configure() {
bind(NfcManager.class).to(Nfc60Manager.class);
}
}
public interface WifiManager {
//bunch of methods to implement
}
public interface WifiProcessor {
//bunch of methods to implement
}
public interface NfcManager {
//bunch of methods to implement
}
public class SuperModule extends AbstractModule {
private final List<Module> chosenModules = new ArrayList<Module>();
public void addModules(List<Module> features) {
chosenModules.addAll(features);
}
@Override
protected void configure() {
for (Module feature: chosenModules) {
feature.configure(binder())
}
}
}
所以在启动时应用程序会这样做:
SuperModule superModule = new SuperModule();
superModule.addModules(crazyBusinessLogic());
Injector injector = Guice.createInjector(Stage.PRODUCTION, superModule);
其中 crazyBusinessLogic() 读取所有模块的注释,并根据设备属性确定用于每个功能的单个模块。例如:
- OS = 5.0 的三星设备将有 crazyBusinessLogic() 返回列表 { new WifiSamsung44Module(), new NfcDefaultModule() }
- OS = 7.0 的三星设备将有 crazyBusinessLogic() 返回列表 { new WifiSamsung44Module(), new Nfc60Module() }
- OS = 7.0 的 Nexus 设备将有 crazyBusinessLogic() 返回列表 { new Wifi44Module(), new Nfc60Module() }
- 等等....
有没有办法对 Dagger 做同样的事情? Dagger 似乎要求您在 Component 注释中传递模块列表。
我阅读了一篇博客,该博客似乎在做一个小型演示,但它看起来很笨拙,额外的 if 语句和额外的组件接口可能会导致我的代码膨胀。
https://blog.davidmedenjak.com/android/2017/04/28/dagger-providing-different-implementations.html
有什么方法可以像在 Guice 中那样使用从函数返回的模块列表?如果没有,最接近的方法是什么可以最大程度地减少重写注释和 crazyBusinessLogic() 方法?
【问题讨论】: