在 DI 模块中提供 Retrofit 时如何从元数据中读取主机名?

How to read hostname from meta-data when providing Retrofit in DI Modules?

我正在使用 Dagger 2 + Retrofit 来实现我的接口,其中 sends/receives 数据 to/from 我的网络服务

我指的是 Philippe BOISNEY 的 AppModule.java 如下

private static String BASE_URL = "https://api.github.com/";

@Provides
Gson provideGson() { return new GsonBuilder().create(); }

@Provides
Retrofit provideRetrofit(Gson gson) {
    Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create(gson))
            .baseUrl(BASE_URL)
            .build();
    return retrofit;
}

但是我有一个问题,如果我的 Web 服务有多个主机,例如 ProductionStaging发展?

我已经在 AndroidManifest.xml 中设置了连接到构建配置的不同主机,但我不知道如何读取 AppModule 中的元数据,以便将 BASE_URL 替换为相应的构建配置

请多多指教,谢谢

您可以在 build.gradle 中定义多种风格类型,如开发、生产和阶段,并为每种风格定义构建配置变量

productFlavors {
    dev {
        buildConfigField "String", "SERVER_URL", "\"your dev url\""
    }
    stage {
        buildConfigField "String", "SERVER_URL", "\"your stage url\""
    }
    prod {
        buildConfigField "String", "SERVER_URL", "\"your prod url\""
    }
}

然后使用它

private static String BASE_URL = BuildConfig.SERVER_URL;

如果你喜欢使用 dagger 动态提供它,你可以那样做

@Module
public class AppModule {
    @Named("server_url")
    @Provides
    String provideServerUrl() {
        return "https://api.github.com/";
    }

    @Provides
    Retrofit provideRetrofit(Gson gson, @Named("server_url") String url) {
        Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create(gson))
            .baseUrl(url)
            .build();
        return retrofit;
    }
}

使用 dagger 动态提供服务器 url 的另一种方法 - 使用构建器。例如,

@Component(AppModule.class)
interface AppComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder serverUrl(@Named("server_url") String url);

        AppComponent build();
    }
}

@Module
public class AppModule {
    @Provides
    Retrofit provideRetrofit(Gson gson, @Named("server_url") String url) {
        Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create(gson))
            .baseUrl(url)
            .build();
        return retrofit;
    }
}

DaggerAppComponent.Builder()
    .appModule(new AppModule())
    .serverUrl("https://api.github.com/")
    .build();

我放弃了从AndroidManefist的元数据中读取对应的主机,而是参考@ConstOrVar的建议改用另一种方法

这是我的 app/build.gradle,我有 2 种风格,分别描述了我的暂存和生产主机

productFlavors {
    production {
        buildConfigField("String", "SERVER_HOST", "\"myproductionost.com\"")
    }
    staging {
        buildConfigField("String", "SERVER_HOST", "\"mystaginghost.com\"")
    }
}

然后这是我的 AppModule.java

中的代码
@Module
public class AppModule {

    @Provides
    Retrofit provideRetrofit(Gson gson) {
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(gson)) 
                .baseUrl("https://" + BuildConfig.SERVER_HOST)
                .build();
        return retrofit;
    }
}

通过这样做,Retrofit 将根据 BuildVariant 自动告诉它应该与哪个 webservice 主机对话