Integrate thư viện vào project Android
build.gradle để giai quyết vấn đề đó. dependencies {
// other classpath definitions here
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
Thêm đoạn script sau vào app/build.gradledependencies {
// apt command comes from the android-apt plugin
apt 'com.google.dagger:dagger-compiler:2.7'
compile 'com.google.dagger:dagger:2.7'
provided 'javax.annotation:jsr250-api:1.0'
}
Dagger đang được hỗ trợ rất tốt nên các version sẽ được cập nhật
thường xuyên, do đó các bạn cần chú ý đến version của các dependencies
cũng như plugin sẽ được sử dụng.
Implementation
Các thành phần chính của Dagger
- Service: hay còn gọi là Module, là nơi cung cấp các abstract để inject vào high-level class.
- Client: là nơi sử dụng các Service được inject vào thông qua một Injector.
- DI container : thường được biết đến như là Object Graph, nơi cung cấp các Dependency (Service) sẽ được inject vào Client.
Annotation
Dagger sử dụng các annotation để implement nhằm tạo sự đơn gian cũng như tường minh của code.@Scope: annotation định nghĩa vòng đời tồn tại của Object graph, nó thật sự hữu ích trong việc quản lý vòng đời của các Service sẽ được cung cấp cho Client. Chúng ta có thể define các loại Scope khác nhau như một annotation mới và sử dụng trong từng trường hợp cụ thể. Dưới đây là một ví dụ:
@Scope
@Documented
@Retention(value=RetentionPolicy.RUNTIME)
public @interface ActivityScope
{
}
@Module: annotation định nghĩa một Module, nơi sẽ cung cấp các service sẽ được inject vào Client.@Provide: annotation được sử dụng trong một Module, định nghĩa các Service sẽ được cung cấp.@Component: annotation định nghĩa một Component, là nơi sẽ expose ra toàn bộ các Service mà bạn dự định sẽ cung cấp cho Client.@Inject: annotation được sử dụng ở Client, thông báo rằng service này sẽ được inject vào Client.@Singleton: annotation sử dụng ở Module, đánh dấu Service được cung cấp dưới dạng một Singleton object.
Implementation
Chúng ta sẽ implement một Module, dùng để cung cấp các service giúp thao tác với API, parse dữ liệu trả về … Ta sẽ hình dung các Service cần cung cấp đến client và các Service cần để làm dependency lẫn nhau.@Module
public class NetModule {
private static final String BASE_ENPOINT = "http://dummy.endpoint";
// Dagger will only look for methods annotated with @Provides
@Provides
@Singleton
// Application reference must come from AppModule.class
SharedPreferences providesSharedPreferences(Application application) {
return PreferenceManager.getDefaultSharedPreferences(application);
}
@Provides
@Singleton
Cache provideOkHttpCache(Application application) {
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(application.getCacheDir(), cacheSize);
return cache;
}
@Provides
@Singleton
Gson provideGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
return gsonBuilder.create();
}
@Provides
@Singleton
OkHttpClient provideOkHttpClient(Cache cache) {
OkHttpClient client = new OkHttpClient();
client.setCache(cache);
return client;
}
@Provides
@Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(BASE_ENPOINT)
.client(okHttpClient)
.build();
return retrofit;
}
}
- Ở ví dụ trên, ta cần một annotation
@Moduleđể khai báo một module mới. Trong module này, ta sẽ sử dụng@Provideđể định nghĩa các Service sẽ được cung cấp và@Singletonđể đánh dấu rằng các Service này sẽ được khởi tạo một lần. Rõ ràng, chúng ta thấy có những Service được định nghĩa để cung cấp cho Client (ví dụ như Retrofit), cũng có những service được định nghĩa để làm dependency cho các service khác (Gson, OkHttpClient, Cache…)
@Singleton
@Component(modules={NetModule.class})
public interface NetComponent {
Retrofit retrofit();
Gson gson();
}
Component NetComponent sẽ expose cho client 2 service là Retrofit và Gson, khi sử dụng ở client, chúng ta sẽ inject nó vào bằng annotation @Inject, sẽ xem xét ở những ví dụ sau.NetComponent sẽ provide các Service được sử dụng trong toàn app, do đó, scope của nó sẽ và Application hay Graph Object được tạo ra và tồn tại theo vòng đời của Application. Chúng ta tiến hành implement nó trong Application class.public class MyApp extends Application {
private NetComponent mNetComponent;
@Override
public void onCreate() {
super.onCreate();
mNetComponent = DaggerNetComponent.builder()
// list of modules that are part of this component need to be created here too
.netModule(new NetModule())
.build();
}
public NetComponent getNetComponent() {
return mNetComponent;
}
}
Chúng ta sẽ tiếp tục implement một Component khác, có dependency là NetComponent đã được định nghĩa ở trên. Component này sẽ được sử dụng như một Injector và cung cấp các Service cho client.@ActivityScope
@Component(dependencies = NetComponent.class, modules= NetModule.class)
public interface AppComponent {
void inject(MyActivity activity);
}
Annotation @ActivityScope được sử dụng để hạn chế scope của Object Graph, chỉ tồn tại trong vòng đời của một Activity. Ta sẽ tiến hành implement Client.public class MyActivity extends Activity {
@Inject Retrofit retrofit;
@Inject Gson gson;
@Overide
public void onCreate(Bundle savedInstance) {
DaggerAppComponent.builder()
.netComponent(((MyApp)getApplication()).getNetComponent())
.build().inject(this);
}
}
Dagger sẽ tự động tìm kiếm trong Object graph của mình và inject vào Client các Service được đánh dấu bởi @Inject và chúng ta có thể sử dụng chúng mà không cần quan tâm đến cách khởi tạo như thế nào nhé, đó cũng chính là tư tưởng của DI.
Comments
Post a Comment