Tôi đang cố gắng quấn đầu quanh phạm vi trong Dagger 2, cụ thể là vòng đời của đồ thị có phạm vi. Làm thế nào để bạn tạo ra một thành phần sẽ được làm sạch khi bạn rời khỏi phạm vi.
Trong trường hợp ứng dụng Android, sử dụng Dagger 1.x, bạn thường có phạm vi gốc ở cấp ứng dụng mà bạn sẽ mở rộng để tạo phạm vi con ở cấp độ hoạt động.
public class MyActivity {
private ObjectGraph mGraph;
public void onCreate() {
mGraph = ((MyApp) getApplicationContext())
.getObjectGraph()
.plus(new ActivityModule())
.inject(this);
}
public void onDestroy() {
mGraph = null;
}
}
Phạm vi con tồn tại miễn là bạn giữ một tham chiếu đến nó, trong trường hợp này là vòng đời của Hoạt động của bạn. Việc bỏ tham chiếu trong onDestroy đảm bảo đồ thị có phạm vi được tự do thu gom rác.
BIÊN TẬP
Jesse Wilson gần đây đã đăng một mea culpa
Dagger 1.0 đã làm hỏng tên phạm vi của nó ... Chú thích @Singleton được sử dụng cho cả biểu đồ gốc và biểu đồ tùy chỉnh, vì vậy thật khó để tìm ra phạm vi thực tế của một sự vật.
và mọi thứ khác tôi đã đọc / nghe điểm về Dagger 2 cải thiện cách thức hoạt động của phạm vi, nhưng tôi đang cố gắng để hiểu sự khác biệt. Theo nhận xét của @Kirill Boyarshinov bên dưới, vòng đời của một thành phần hoặc phụ thuộc vẫn được xác định, như thường lệ, bằng các tham chiếu cụ thể. Vì vậy, sự khác biệt giữa phạm vi Dagger 1.x và 2.0 hoàn toàn là vấn đề rõ ràng về ngữ nghĩa?
Sự hiểu biết của tôi
Dao găm 1.x
Phụ thuộc là một trong hai @Singleton
hoặc không. Điều này cũng đúng với sự phụ thuộc trong biểu đồ gốc và biểu đồ con, dẫn đến sự mơ hồ về biểu đồ mà sự phụ thuộc bị ràng buộc (xem Trong Dagger là Singletons trong biểu đồ con được lưu trong bộ nhớ cache hoặc chúng sẽ luôn được tạo lại khi biểu đồ con hoạt động mới được xây dựng? )
Dao găm 2.0
Phạm vi tùy chỉnh cho phép bạn tạo phạm vi rõ ràng về ngữ nghĩa, nhưng tương đương về mặt chức năng với việc áp dụng @Singleton
trong Dagger 1.x.
// Application level
@Singleton
@Component( modules = MyAppModule.class )
public interface MyAppComponent {
void inject(Application app);
}
@Module
public class MyAppModule {
@Singleton @Named("SingletonScope") @Provides
StringBuilder provideStringBuilderSingletonScope() {
return new StringBuilder("App");
}
}
// Our custom scope
@Scope public @interface PerActivity {}
// Activity level
@PerActivty
@Component(
dependencies = MyAppComponent.class,
modules = MyActivityModule.class
)
public interface MyActivityComponent {
void inject(Activity activity);
}
@Module
public class MyActivityModule {
@PerActivity @Named("ActivityScope") @Provides
StringBuilder provideStringBuilderActivityScope() {
return new StringBuilder("Activity");
}
@Name("Unscoped") @Provides
StringBuilder provideStringBuilderUnscoped() {
return new StringBuilder("Unscoped");
}
}
// Finally, a sample Activity which gets injected
public class MyActivity {
private MyActivityComponent component;
@Inject @Named("AppScope")
StringBuilder appScope
@Inject @Named("ActivityScope")
StringBuilder activityScope1
@Inject @Named("ActivityScope")
StringBuilder activityScope2
@Inject @Named("Unscoped")
StringBuilder unscoped1
@Inject @Named("Unscoped")
StringBuilder unscoped2
public void onCreate() {
component = Dagger_MyActivityComponent.builder()
.myApplicationComponent(App.getComponent())
.build()
.inject(this);
appScope.append(" > Activity")
appScope.build() // output matches "App (> Activity)+"
activityScope1.append("123")
activityScope1.build() // output: "Activity123"
activityScope2.append("456")
activityScope1.build() // output: "Activity123456"
unscoped1.append("123")
unscoped1.build() // output: "Unscoped123"
unscoped2.append("456")
unscoped2.build() // output: "Unscoped456"
}
public void onDestroy() {
component = null;
}
}
Việc sử dụng @PerActivity
truyền đạt ý định của bạn về vòng đời của thành phần này, nhưng cuối cùng bạn có thể sử dụng thành phần này ở bất cứ đâu / bất cứ lúc nào. Lời hứa duy nhất của Dagger là, đối với một thành phần nhất định, các phương thức chú thích phạm vi sẽ trả về một thể hiện duy nhất. Tôi cũng giả sử Dagger 2 sử dụng chú thích phạm vi trên thành phần để xác minh rằng các mô-đun chỉ cung cấp các phụ thuộc có cùng phạm vi hoặc không nằm trong phạm vi.
Tóm tắt
Các phụ thuộc vẫn là singleton hoặc non-singleton, nhưng @Singleton
hiện được dành cho các trường hợp singleton cấp ứng dụng và phạm vi tùy chỉnh là phương pháp ưa thích để chú thích các phụ thuộc singleton với vòng đời ngắn hơn.
Nhà phát triển chịu trách nhiệm quản lý vòng đời của các thành phần / phụ thuộc bằng cách bỏ các tham chiếu không còn cần thiết và chịu trách nhiệm đảm bảo rằng các thành phần chỉ được tạo một lần trong phạm vi mà chúng được dự định, nhưng chú thích phạm vi tùy chỉnh giúp dễ dàng xác định phạm vi đó .
Câu hỏi $ 64k *
Sự hiểu biết của tôi về phạm vi Dagger 2 và vòng đời có đúng không?
* Không thực sự là một câu hỏi $ 64'000.
plus()
tham chiếu đến biểu đồ mới được lưu trữ trong Activity và bị ràng buộc với vòng đời của nó (được quy định trongonDestroy
). Đối với phạm vi, chúng đảm bảo việc triển khai thành phần của bạn được tạo mà không có lỗi tại thời gian biên dịch, với mọi phụ thuộc được thỏa mãn. Vì vậy, nó không chỉ cho mục đích tài liệu. Kiểm tra một số ví dụ từ chủ đề này .