先看代碼
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);
}
}
打印結(jié)果:
E/retrofit1----: address: retrofit2.Retrofit@5707fc6
E/retrofit2----: address: retrofit2.Retrofit@f8eb87
在項(xiàng)目開發(fā)中, Retrofit 應(yīng)該是全局的,單一的.
那如何修改呢?
修改 NetWorkModule , 在具備單一性的函數(shù)上添加 @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);
}
}
同時(shí),在Component 容器上也要添加 @Singleton 注解.
@Singleton
@Component(modules = NetWorkModule.class)
public interface ApplicationCommponent {
void inject(TextDaggerActivity mainActivity);
}
此時(shí),再次運(yùn)行代碼.
打印結(jié)果:
E/retrofit1----: address: retrofit2.Retrofit@5707fc6
E/retrofit2----: address: retrofit2.Retrofit@5707fc6
如此,看樣子確實(shí)是實(shí)現(xiàn)了單例模式.
創(chuàng)建TextDaggerActivity2.class. 同時(shí)修改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);
}
}
兩個(gè)Activity 都聲明了Retrofit, 并使用@Inject 注入. 看一下執(zhí)行結(jié)果
打印結(jié)果:
E/retrofit1----: address: retrofit2.Retrofit@5707fc6
E/retrofit2----: address: retrofit2.Retrofit@5707fc6
E/retrofit3----: address: retrofit2.Retrofit@48b72b9
可見Dagger 中的@Singleton注解并不是真正意義上的單例模式瓣戚。而是局部單例模式.
在Dagger 中,@Singleton注解用于標(biāo)記一個(gè)對(duì)象的作用域范圍,表示在同一個(gè)作用域內(nèi)只會(huì)創(chuàng)建一個(gè)對(duì)象實(shí)例,但它不能保證對(duì)象的唯一性.
拿到代碼上來說, 被@Singleton 修飾的容器,它們的作用域一個(gè)在TextDaggerActivity, 另一個(gè)在TextDaggerActivity2 進(jìn)行create(), 兩個(gè)是不同的作用域的,所以也就導(dǎo)致了局部單例.
如何實(shí)現(xiàn)真正意義上的單例呢?
自定義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);
此時(shí),再次運(yùn)行代碼.
打印結(jié)果:
E/retrofit1----: address: retrofit2.Retrofit@5707fc6
E/retrofit2----: address: retrofit2.Retrofit@5707fc6
E/retrofit3----: address: retrofit2.Retrofit@5707fc6
總結(jié) :
Dagger中的@Singleton注解并不是真正意義上的單例模式。在Dagger中焦读,@Singleton注解用于標(biāo)記一個(gè)對(duì)象的作用域范圍子库,表示在同一個(gè)作用域內(nèi)只會(huì)創(chuàng)建一個(gè)對(duì)象實(shí)例,但它并不能保證這個(gè)對(duì)象的唯一性.