【问题标题】:Should I use one global Retrofit instance or create one for each request in Android?我应该使用一个全局 Retrofit 实例还是为 Android 中的每个请求创建一个?
【发布时间】:2016-12-14 07:02:08
【问题描述】:

好吧,我现在迷失在使用 Retrofit... 起初我编写了一个 Singleton 助手类,它包含一个由 Retrofit 实例创建的服务实例。获取服务并发出 HTTP 请求非常方便,但后来我发现无法从 SharedPreferences 获取访问令牌,因为帮助程序实例是静态的。因为我使用Authenticator接口来处理认证,所以在发出请求时无法传递访问令牌。我尝试扩展 Application 类并将 Application 实例保存在静态字段中,但 Android Studio 给了我一个警告(Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run))。

所以现在我有另一个选择:编写一个静态帮助器方法,对于每个请求,它接受访问令牌,构建一个 Retrofit 实例,创建一个服务实例并发出请求。现在我很困惑这是否是最佳实践。重用一个服务实例和为每个请求创建服务有什么区别?

PS:上面service这个词是指someRetrofit.create(someServiceInterface.class)创建的服务实例,而不是android.app.Service

【问题讨论】:

  • 有趣的是,在我的项目中它没有给出关于内存泄漏的警告。但无论如何,这只是一个警告。持有对应用程序的静态引用并没有错。我在这里有一个答案 stackoverflow.com/questions/14057273/… 。所以我的建议是只使用单个应用程序,不要担心这个警告。
  • @Budius 其实我也想知道重用someRetrofit.create(xxx.class)创建的单个实例和每次请求都这样做的区别。
  • 我从不深入挖掘,但似乎该实例将控制/持有线程、回调、拦截器,因此您可能不应该每次都创建一个新实例。

标签: java android retrofit2 okhttp3


【解决方案1】:

我还建议您只使用单例方法,因为它从设计角度来看也很好。

如果您创建多个服务实例,每个实例都可能具有不同的网络属性,例如 readTimeout 、 writeTimeout 、响应日志记录属性等,或者您必须将它们全部设置为一个属性,如果我们在团队中工作,这可能会给你很头疼。

我面临的一个用户案例是,在稍后的某个时间点,您的后端团队为每个请求(如设备操作系统版本)添加额外的标头参数,然后您必须将此属性添加到所有改造客户端,这将是一种痛苦。

这是我的代码的 sn-p,我如何处理标题。

public static Retrofit getRestAdapter(final HashMap<String, String> requestHeaderMap) {
    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
            .addNetworkInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request.Builder builder = chain.request().newBuilder();
                    Set<Map.Entry<String, String>> entrySet = requestHeaderMap.entrySet();
                    for (Map.Entry<String, String> entry : entrySet) {
                        if (entry.getValue().isEmpty())
                            builder.removeHeader(entry.getKey());
                        else
                            builder.addHeader(entry.getKey(), entry.getValue());
                    }

                    Request request = builder.build();
                    return chain.proceed(request);
                }


            }).build();

    return new Retrofit.Builder()
            .baseUrl(Constants.BASE_URL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
}

requestHeaderMap 的 is 实例是全局实例,并且使用 observable 模式将数据推入其中。

我希望这可以帮助您做出决定。

【讨论】:

    猜你喜欢
    • 2023-03-18
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-07
    • 2021-11-16
    相关资源
    最近更新 更多