Tôi đã làm việc với dagger2 một thời gian. Và tôi đã bối rối hơn khi tạo một thành phần / mô-đun riêng cho mỗi Hoạt động / Phân mảnh. Vui lòng giúp tôi làm rõ điều này:
Ví dụ: Chúng tôi có một ứng dụng và ứng dụng có khoảng 50 màn hình. Chúng tôi sẽ triển khai mã theo sau mẫu MVP và Dagger2 cho DI. Giả sử rằng chúng ta có 50 hoạt động và 50 người thuyết trình.
Theo ý kiến của tôi, thông thường chúng ta nên tổ chức mã như thế này:
Tạo một AppComponent và AppModule sẽ cung cấp tất cả các đối tượng sẽ được sử dụng khi ứng dụng đang mở.
@Module public class AppModule { private final MyApplicationClass application; public AppModule(MyApplicationClass application) { this.application = application; } @Provides @Singleton Context provideApplicationContext() { return this.application; } //... and many other providers } @Singleton @Component( modules = { AppModule.class } ) public interface AppComponent { Context getAppContext(); Activity1Component plus(Activity1Module module); Activity2Component plus(Activity2Module module); //... plus 48 methods for 48 other activities. Suppose that we don't have any other Scope (like UserScope after user login, ....) }
Tạo ActivityScope:
@Scope @Documented @Retention(value=RUNTIME) public @interface ActivityScope { }
Tạo Thành phần và Mô-đun cho mỗi Hoạt động. Thông thường tôi sẽ đặt chúng dưới dạng các lớp tĩnh trong lớp Hoạt động:
@Module public class Activity1Module { public LoginModule() { } @Provides @ActivityScope Activity1Presenter provideActivity1Presenter(Context context, /*...some other params*/){ return new Activity1PresenterImpl(context, /*...some other params*/); } } @ActivityScope @Subcomponent( modules = { Activity1Module.class } ) public interface Activity1Component { void inject(Activity1 activity); // inject Presenter to the Activity } // .... Same with 49 remaining modules and components.
Đó chỉ là những ví dụ rất đơn giản để cho thấy cách tôi thực hiện điều này.
Nhưng một người bạn của tôi vừa đưa cho tôi một cách triển khai khác:
Tạo PresenterModule sẽ cung cấp cho tất cả những người thuyết trình:
@Module public class AppPresenterModule { @Provides Activity1Presenter provideActivity1Presentor(Context context, /*...some other params*/){ return new Activity1PresenterImpl(context, /*...some other params*/); } @Provides Activity2Presenter provideActivity2Presentor(Context context, /*...some other params*/){ return new Activity2PresenterImpl(context, /*...some other params*/); } //... same with 48 other presenters. }
Tạo AppModule và AppComponent:
@Module public class AppModule { private final MyApplicationClass application; public AppModule(MyApplicationClass application) { this.application = application; } @Provides @Singleton Context provideApplicationContext() { return this.application; } //... and many other provides } @Singleton @Component( modules = { AppModule.class, AppPresenterModule.class } ) public interface AppComponent { Context getAppContext(); public void inject(Activity1 activity); public void inject(Activity2 activity); //... and 48 other methods for 48 other activities. Suppose that we don't have any other Scope (like UserScope after user login, ....) }
Giải thích của anh ấy là: Anh ấy không phải tạo các thành phần và mô-đun cho mỗi hoạt động. Tôi nghĩ ý kiến của bạn bè tôi hoàn toàn không tốt chút nào, nhưng xin hãy sửa cho tôi nếu tôi sai. Đây là những lý do:
Rò rỉ nhiều bộ nhớ :
- Ứng dụng sẽ tạo ra 50 người thuyết trình ngay cả khi người dùng chỉ mở 2 Hoạt động.
- Sau khi người dùng đóng một Hoạt động, người trình bày của Hoạt động đó sẽ vẫn
Điều gì xảy ra nếu tôi muốn tạo hai phiên bản của một Hoạt động? (làm thế nào anh ta có thể tạo ra hai người thuyết trình)
Sẽ mất rất nhiều thời gian để khởi tạo ứng dụng (vì phải tạo nhiều người trình bày, đối tượng, ...)
Xin lỗi vì một bài dài, nhưng hãy giúp tôi làm rõ điều này cho tôi và bạn tôi, tôi không thể thuyết phục anh ta. Ý kiến của bạn sẽ được đánh giá rất cao.
/ ------------------------------------------------- ---------------------- /
Chỉnh sửa sau khi làm bản demo.
Đầu tiên, cảm ơn câu trả lời của @pandawarrior. Tôi nên tạo một Demo trước khi tôi hỏi câu hỏi này. Tôi hy vọng kết luận của tôi ở đây có thể giúp ích cho người khác.
- Những gì bạn tôi đã làm không gây ra rò rỉ bộ nhớ trừ khi anh ấy đặt bất kỳ Phạm vi nào cho các phương thức Cung cấp. (Ví dụ: @Singleton hoặc @UserScope, ...)
- Chúng tôi có thể tạo nhiều người trình bày, nếu phương thức Cung cấp không có bất kỳ Phạm vi nào. (Vì vậy, điểm thứ hai của tôi cũng sai)
- Dagger sẽ chỉ tạo người trình bày khi họ cần. (Vì vậy, ứng dụng sẽ không mất nhiều thời gian để khởi tạo, tôi đã nhầm lẫn với Lazy Injection)
Vì vậy, tất cả những lý do tôi đã nói ở trên hầu hết là sai. Nhưng nó không có nghĩa là chúng ta nên làm theo ý tưởng của bạn tôi, vì hai lý do:
Nó không tốt cho kiến trúc của nguồn, khi anh ta loại bỏ tất cả những người trình bày trong mô-đun / thành phần. (Nó vi phạm nguyên tắc phân tách Giao diện , có thể cả nguyên tắc Trách nhiệm đơn lẻ ).
Khi chúng tôi tạo một Thành phần phạm vi, chúng tôi sẽ biết khi nào nó được tạo và khi nào nó bị phá hủy, đó là một lợi ích rất lớn để tránh rò rỉ bộ nhớ. Vì vậy, đối với mỗi Hoạt động, chúng ta nên tạo một Thành phần bằng @ActivityScope. Hãy tưởng tượng, với việc triển khai bạn bè của tôi, mà chúng tôi quên đặt một số Phạm vi trong phương thức Nhà cung cấp => rò rỉ bộ nhớ sẽ xảy ra.
Theo tôi, với một ứng dụng nhỏ (chỉ một vài màn hình mà không có nhiều phần phụ thuộc hoặc có các phần phụ thuộc tương tự), chúng tôi có thể áp dụng ý tưởng của bạn bè tôi, nhưng tất nhiên là không nên.
Thích đọc thêm về: Điều gì quyết định vòng đời của một thành phần (đồ thị đối tượng) trong Dagger 2? Phạm vi hoạt động của Dagger2, tôi cần bao nhiêu mô-đun / thành phần?
Và một lưu ý nữa: Nếu bạn muốn xem khi nào đối tượng bị hủy, bạn có thể gọi các phương thức đó cùng nhau và GC sẽ chạy ngay lập tức:
System.runFinalization();
System.gc();
Nếu bạn chỉ sử dụng một trong những phương pháp này, GC sẽ chạy muộn hơn và bạn có thể nhận được kết quả sai.
ControllerModule
sẽ tạo một mẫu mớiPresenter
và sau đó người trình bày được đưa vào dấuActivity
hoặcFragment
. Bất kỳ ý kiến vững chắc ủng hộ hoặc chống lại điều này?