Dagger 作用域Singleton

2023-07-17  本文已影响0人  coke613

先看代码

public  interface Api {
    @POST("/api/sdk/v1/init")
    Call<String> login();
}

// 声明Module

@Module
public class NetWorkModule {
    @Provides
    public Retrofit provideRetrofit(){
        return new Retrofit.Builder()
                .baseUrl("https://www.google.com")
                .build();
    }


    @Provides
    public Api providesApi(Retrofit retrofit){
        return retrofit.create(Api.class);
    }

}

// 将Module 装到Component 容器中

@Component(modules = NetWorkModule.class)
public interface ApplicationCommponent {
    void inject(TextDaggerActivity mainActivity);
}
public class TextDaggerActivity extends AppCompatActivity {


   @Inject
   Retrofit retrofit1;

   @Inject
   Retrofit retrofit2;

   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      DaggerApplicationCommponent.create(). inject(this);

      Log.e("retrofit1----","address: "+retrofit1);
      Log.e("retrofit2----","address: "+retrofit2);
   }
}
 打印结果:
E/retrofit1----: address: retrofit2.Retrofit@5707fc6
E/retrofit2----: address: retrofit2.Retrofit@f8eb87

在项目开发中, Retrofit 应该是全局的,单一的.
那如何修改呢?

修改 NetWorkModule , 在具备单一性的函数上添加 @Singleton 注解.

@Module
public class NetWorkModule {
    @Provides
    @Singleton
    public Retrofit provideRetrofit(){
        return new Retrofit.Builder()
                .baseUrl("https://www.google.com")
                .build();
    }  
    @Singleton  
    @Provides
    public Api providesApi(Retrofit retrofit){
        return retrofit.create(Api.class);
    }

}

同时,在Component 容器上也要添加 @Singleton 注解.


@Singleton
@Component(modules = NetWorkModule.class)
public interface ApplicationCommponent {
    void inject(TextDaggerActivity mainActivity);

}

此时,再次运行代码.

打印结果: 
E/retrofit1----: address: retrofit2.Retrofit@5707fc6
E/retrofit2----: address: retrofit2.Retrofit@5707fc6

如此,看样子确实是实现了单例模式.

创建TextDaggerActivity2.class. 同时修改ApplicationCommponent.

@Singleton
@Component(modules = NetWorkModule.class)
public interface ApplicationCommponent {
    void inject(TextDaggerActivity mainActivity);
    void inject(TextDaggerActivity2 mainActivity);

}
public class TextDaggerActivity extends AppCompatActivity {
    ...
    @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
        ...

       startActivity(new Intent(this,TextDaggerActivity2.class));
   }
 
}
public class TextDaggerActivity2 extends AppCompatActivity {

   @Inject
   Retrofit retrofit;

   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      DaggerApplicationCommponent.create(). inject(this);
      Log.e("retrofit3----","address: "+retrofit);
   }
}

两个Activity 都声明了Retrofit, 并使用@Inject 注入. 看一下执行结果

打印结果: 
E/retrofit1----: address: retrofit2.Retrofit@5707fc6
E/retrofit2----: address: retrofit2.Retrofit@5707fc6
E/retrofit3----: address: retrofit2.Retrofit@48b72b9

可见Dagger 中的@Singleton注解并不是真正意义上的单例模式。而是局部单例模式.

在Dagger 中,@Singleton注解用于标记一个对象的作用域范围,表示在同一个作用域内只会创建一个对象实例,但它不能保证对象的唯一性.

拿到代码上来说, 被@Singleton 修饰的容器,它们的作用域一个在TextDaggerActivity, 另一个在TextDaggerActivity2 进行create(), 两个是不同的作用域的,所以也就导致了局部单例.

如何实现真正意义上的单例呢?
自定义Application, 被@Singleton 修饰的容器作用域指定为全局.

public class App extends Application {

   public static ApplicationCommponent applicationCommponent;

   @Override
   public void onCreate() {
      super.onCreate();
      applicationCommponent = DaggerApplicationCommponent.create();
   }
}

// TextDaggerActivity  & TextDaggerActivity2 修改为:
App.applicationCommponent.injectUser(this);

此时,再次运行代码.

打印结果: 
E/retrofit1----: address: retrofit2.Retrofit@5707fc6
E/retrofit2----: address: retrofit2.Retrofit@5707fc6
E/retrofit3----: address: retrofit2.Retrofit@5707fc6

总结 :

Dagger中的@Singleton注解并不是真正意义上的单例模式。在Dagger中,@Singleton注解用于标记一个对象的作用域范围,表示在同一个作用域内只会创建一个对象实例,但它并不能保证这个对象的唯一性.

上一篇 下一篇

猜你喜欢

热点阅读