如何为Retrofit 2创建一个单例?

5
如果存在多个Retrofit调用,我该如何创建一个Retrofit的单例,以便在类中不会有重复的代码,并摆脱不必要的代码。

2
我使用了Dagger 2来实现这个。https://github.com/codepath/android_guides/wiki/Dependency-Injection-with-Dagger-2 - Raghunandan
创建Retrofit的单例与创建普通的单例类没有什么不同。有多种方法可以实现,这些方法已经在这里和谷歌上发布过了。 - ashkhn
5个回答

8

以下是一个例子,但是!虽然它可能看起来华丽且易于使用,但单例模式是有害的。如果可能的话,请尝试避免使用它们。解决这个问题的方法之一是使用依赖注入。

无论如何。

public class Api {
    private static Api instance = null;
    public static final String BASE_URL = "your_base_url";

    // Keep your services here, build them in buildRetrofit method later
    private UserService userService;

    public static Api getInstance() {
        if (instance == null) {
            instance = new Api();
        }

        return instance;
    }

    // Build retrofit once when creating a single instance
    private Api() {
        // Implement a method to build your retrofit
        buildRetrofit(BASE_URL);
    }

    private void buildRetrofit() {
        Retrofit retrofit = ...

        // Build your services once
        this.userService = retrofit.create(UserService.class);
        ...
    }

    public UserService getUserService() {
        return this.userService;
    }
    ...
}

现在你拥有了一个集大成者,好好利用它吧。
UserService userService = Api.getInstance().getUserService();

1
正如你所说,它们是恶意的。几周前我遇到了一个问题。当在不同后端使用相同的API时(因此域在运行时更改),单例模式不会从工厂创建新实例。像koin中使用工厂模式解决了这个问题。但现在我有成千上万的API实例躺在那里。有什么改进的想法吗? - kaulex

2

实现单例模式最简单的方法是将类的构造函数设为私有。

  1. 饱汉式(Eager initialization):

在饱汉式中,单例类的实例在类加载时创建,这是创建单例类的最简单方法。

public class SingletonClass {

private static volatile SingletonClass sSoleInstance = new SingletonClass();

    //private constructor.
    private SingletonClass(){}

    public static SingletonClass getInstance() {
        return sSoleInstance;
    }
}
  1. 懒加载:

该方法会检查该类的实例是否已经被创建?如果是,则我们的方法(getInstance())将返回旧实例,否则它将在JVM中创建单例类的新实例并返回该实例。这种方法被称为懒加载。

public class SingletonClass {

    private static SingletonClass sSoleInstance;

    private SingletonClass(){}  //private constructor.

    public static SingletonClass getInstance(){
        if (sSoleInstance == null){ //if there is no instance available... create new one
            sSoleInstance = new SingletonClass();
        }

        return sSoleInstance;
   }
}

除了Java反射API、线程安全和序列化安全单例模式外,还有其他一些内容。

请参考此引用以获取更多详细信息和深入理解单例对象创建。

https://medium.com/@kevalpatel2106/digesting-singleton-design-pattern-in-java-5d434f4f322


1
public class Singleton  {

    private static Singleton INSTANCE = null;

    // other instance variables can be here

    private Singleton() {};

    public static Singleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return(INSTANCE);
    }

    // other instance methods can follow 
}



import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitClient {

    private static Retrofit retrofit = null;

    public static Retrofit getClient(String baseUrl) {
        if (retrofit==null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}




@Module
public class NetworkModule {

    @Provides
    @Singleton
    public Gson gson() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        return gsonBuilder.create();
    }

    @Provides
    @Singleton
    public HttpLoggingInterceptor loggingInterceptor() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(
                message -> Timber.i(message));
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return interceptor;
    }

    @Provides
    @Singleton
    public Cache cache(File cacheFile) {
        return new Cache(cacheFile, 10 * 1000 * 1000); //10MB Cache
    }

    @Provides
    @Singleton
    public File cacheFile(@ApplicationContext Context context) {
        return new File(context.getCacheDir(), "okhttp_cache");
    }

    @Provides
    @Singleton
    public OkHttpClient okHttpClient(HttpLoggingInterceptor loggingInterceptor, Cache cache) {
        return new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .cache(cache)
                .build();
    }

    @Provides
    @Singleton
    public Retrofit retrofit(OkHttpClient okHttpClient, Gson gson) {
        return new Retrofit.Builder()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(okHttpClient)
                .baseUrl("you/base/url")
                .build();
    }
}

单例模式是一种最好和简单的设计模式,这里有一个示例...http://thientvse.com/2017/10/android-design-patterns-singleton-pattern/ - hardy thummar

1
public class Singleton {
private volatile static Singleton singleton;
private Singleton(){}
public static Singleton getSingleton(){
    if (singleton == null) {
        synchronized (Singleton.class) {
            if (singleton == null) {
                singleton = new Singleton();
            }
        }
    }
    return singleton;
}

0

我已经在 Kotlin 中尝试过:

class RetrofitClient{

    companion object
    {
        var retrofit:Retrofit?=null;
        fun getRetrofitObject():Retrofit?
        {
            if(retrofit==null)
            {
                synchronized(RetrofitClient ::class.java)
                {
                    retrofit=Retrofit.Builder()
                        .addConverterFactory(GsonConverterFactory.create())
                        .baseUrl("YOUR_BASE_URL")
                        .build()
                }
            }
            return retrofit

        }

    }
}

然后:

var service: ServicesInterface? = RetrofitClient.getRetrofitObject()?.create(ServicesInterface::class.java)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接