Tôi sử dụng Dagger2 cho DI trong ứng dụng Android của mình. Tôi thấy rằng tôi phải viết phương thức tiêm cho mỗi lớp sử dụng trường @Inject. Có cách nào mà tôi có thể chỉ cần tiêm lớp cha mẹ để tôi không phải gọi tiêm trên mỗi phân lớp? Lấy hoạt động chẳng hạn. Tôi có một số BaseActivity
mà mọi Hoạt động mở rộng. Có cách nào mà tôi chỉ có thể tạo ra một phương pháp tiêm trong thành phần cho BaseActivity và chỉ cần gọi tiêm trong onCreate BaseActivity, và @inject lĩnh vực trong các hoạt động phụ được tiêm tự động?Tôi có thể tiêm siêu lớp khi sử dụng dagger2 để tiêm phụ thuộc không?
Trả lời
Hiện không thể thực hiện được. Giải thích bởi Gregory Kick:
Đây là cách các phương pháp thành viên tiêm làm việc:
- Bạn có thể tạo ra một phương pháp tiêm các thành viên cho bất kỳ loại có
@Inject
bất cứ nơi nào trong hệ thống phân cấp các lớp học. Nếu không, bạn sẽ gặp lỗi .- Tất cả
@Inject
thành viên được chỉnh sửa trong toàn bộ phân cấp loại sẽ được tiêm: loại đối số và tất cả siêu kiểu.- Không có thành viên nào được
@Inject
chỉnh sửa cho loại phụ của loại đối số.
Vấn đề này đã được thảo luận here và here, theo dõi những thông tin cập nhật. Nhưng nó không có khả năng thay đổi sớm, gây ra Dagger 2 là close to release.
Dường như họ đã đưa ra quyết định này vì một lý do. Nhưng nó vẫn là một điều đáng tiếc là họ không hỗ trợ điều này vì nó là một IMHO phản trực giác nhỏ. Tuy nhiên, cảm ơn bạn đã trả lời! –
@ Chris.Zou Để hỗ trợ tiêm lớp con, bạn sẽ cần phải thực hiện phản chiếu khi chạy. Nhóm Dagger 2 đã quyết định sớm rằng họ muốn tránh làm công cụ trong thời gian chạy, vì nó chậm hơn và bạn không tìm hiểu về lỗi cho đến khi bạn chạy ứng dụng. – vaughandroid
Tôi gặp phải tình huống tương tự. Một cách để giảm bớt một chút tiêm từ một thành phần chung trong tất cả các Hoạt động như sau:
1) Mở rộng lớp Ứng dụng để có thể tạo thành phần chung và giữ tham chiếu đến nó.
public class ApplicationDagger extends Application {
private ApplicationComponent component;
@Override
public void onCreate(){
super.onCreate();
component = DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(this)).build();
}
public ApplicationComponent getComponent(){
return component;
}
}
2) Tạo một DaggerActivity trừu tượng mà được các thành phần phổ biến từ ứng dụng và gọi một phương pháp trừu tượng injectActivity
, đem lại cho các thành phần như một cuộc tranh cãi. Như thế này:
public abstract class DaggerActivity extends Activity {
@Override
public void onCreate(Bundle saved){
super.onCreate(saved);
ApplicationComponent component = ((ApplicationDagger) getApplication()).getComponent();
injectActivity(component);
}
public abstract void injectActivity(ApplicationComponent component);
}
3) Cuối cùng, bạn phải thực sự tiêm mỗi Activity
kéo dài DaggerActivity
. Nhưng điều này có thể được thực hiện với ít nỗ lực hơn, vì bạn phải thực hiện phương thức abstract
nếu không bạn sẽ nhận được các lỗi biên dịch. Ở đây chúng tôi đi:
public class FirstActivity extends DaggerActivity {
@Inject
ClassToInject object;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//initialize your Activity
}
@Override
public void injectActivity(ApplicationComponent component) {
component.inject(this);
}
}
Tất nhiên, bạn vẫn phải khai báo từng Hoạt động một cách rõ ràng trong Hợp phần của bạn.
UPDATE: tiêm chích @ActivityScope đối tượng vào mảnh vỡ
Tại một số điểm, tôi cần phải sử dụng custom scopes để ràng buộc đối tượng đến một chu kỳ sống Activity
. Tôi quyết định mở rộng bài đăng này vì nó có thể giúp một số người.
Hãy nói rằng bạn có một lớp @ModuleActivityModule
và @Subcomponent giao diện ActivityComponent
.
Bạn cần sửa đổi DaggerActivity
. Việc mở rộng Activities
mở rộng DaggerActivity
sẽ cần phải triển khai phương thức mới (thay đổi chữ ký).
public abstract class ActivityDagger extends AppCompatActivity {
ComponentActivity component;
@Override
protected void onCreate(Bundle savedInstanceState) {
component = ((ApplicationDagger) getApplication()).getComponent().plus(new ActivityModule(this));
injectActivity(component);
super.onCreate(savedInstanceState);
}
ActivityComponent getComponent() {
return component;
}
public abstract void injectActivity(ActivityComponent component);
}
Sau đó, một lớp FragmentDagger
mở rộng Fragment
thể được tạo ra như thế này:
public abstract class FragmentDagger extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityDagger activityDagger = (ActivityDagger) getActivity();
ActivityComponent component = activityDagger.getComponent();
injectFragment(component);
}
public abstract void injectFragment(ActivityComponent component);
}
Đối với Activities
, các Fragments
mở rộng FragmentDagger
chỉ có một phương pháp để thực hiện:
public abstract void injectFragment(ActivityComponent component);
Bạn sẽ có thể sử dụng lại Fragments
bất cứ nơi nào bạn muốn. Lưu ý rằng phương pháp super.onCreated()
trong ActivityDagger
nên được gọi sau khi khởi tạo thành phần. Nếu không, bạn sẽ nhận được NullPointerException khi trạng thái Activity
được tạo lại, bởi vì phương pháp super.onCreate()
của số Fragment
sẽ được gọi.
Cảm ơn lời khuyên! –
Bạn có thể làm một ít hack sử dụng phản ánh:
public class UiInjector {
private static final String METHOD_NAME = "inject";
private final UIComponent component;
public UiInjector(final UIComponent component) {
this.component = component;
}
public void inject(final Object subject) {
try {
component.getClass()
.getMethod(METHOD_NAME, subject.getClass())
.invoke(component, subject);
} catch (final NoSuchMethodException exception) {
throwNoInjectMethodForType(component, subject.getClass());
} catch (final Exception exception) {
throwUnknownInjectionError(exception);
}
}
private void throwNoInjectMethodForType(final Object component, final Class subjectType) {
throw new RuntimeException(component.getClass().getSimpleName() +
" doesn't have inject method with parameter type : " + subjectType);
}
private void throwUnknownInjectionError(final Exception cause) {
throw new RuntimeException("Unknown injection error", cause);
}
}
Trong trường hợp này, bạn vẫn cần phải viết tiêm phương pháp trong một thành phần, nhưng bạn không cần phải 'bơm' phương pháp trong mỗi hoạt động, phân đoạn, xem, bất cứ điều gì.
Tại sao nó hoạt động? khi chúng tôi sử dụng getClass()
trên chủ đề tiêm sẽ có được một lớp hậu duệ, không phải cơ sở.
Thận trọng! Trong trường hợp bạn sử dụng Proguard, bạn cần thêm -keep class <ComponentClass> { *; }
vào quy tắc của mình để giữ các phương pháp tiêm như trong thành phần
- 1. Sử dụng tiêm phụ thuộc cho Properties.Settings.Default?
- 2. Sử dụng chính xác phụ thuộc tiêm
- 3. Khi nào bạn sử dụng tiêm phụ thuộc?
- 4. Tiêm phụ thuộc vào lớp tĩnh
- 5. C# phụ thuộc tiêm - làm thế nào để bạn tiêm một phụ thuộc mà không có nguồn?
- 6. Tiêm phụ thuộc lười biếng
- 7. Tiêm phụ thuộc trong ứng dụng Sinatra
- 8. ASP.NET 5 phụ thuộc tiêm, tiêm với các thông số
- 9. Tôi có nên sử dụng tiêm phụ thuộc trong dự án php của mình không?
- 10. Dagger2 - rỗng thay vì tiêm đối tượng
- 11. Tiêm phụ thuộc với PowerShell
- 12. Tiêm phụ thuộc vào AuthorizationOptions
- 13. Tiêm phụ thuộc với Orleans
- 14. Tiêm phụ thuộc vào MVC
- 15. Angular2 - không đồng bộ phụ thuộc tiêm
- 16. Phá vỡ sự phụ thuộc chu kỳ để sử dụng tiêm phụ thuộc
- 17. Tiêm giá trị vào sự phụ thuộc tiêm
- 18. Tiêm phụ thuộc vào mùa xuân trong lớp siêu trừu tượng
- 19. Mô-đun thử nghiệm tiêm với dagger2
- 20. Tiêm Khẩu phụ thuộc bằng cách sử dụng Injection Dependency
- 21. Tiêm phụ thuộc là gì?
- 22. Tiêm phụ thuộc vào WPF bằng cách sử dụng Ninject
- 23. Sử dụng tiêm phụ thuộc trong thư viện
- 24. Sử dụng nhiều phiên bản dbcontext và tiêm phụ thuộc
- 25. Tiêm phụ thuộc vào AuthorizeAttribute trong thư viện lớp
- 26. Hướng dẫn thiết kế các lớp cho tiêm phụ thuộc
- 27. Tiêm phụ thuộc - Phải làm gì khi bạn có nhiều phụ thuộc?
- 28. Tiêm phụ thuộc với giao diện hoặc lớp học
- 29. Tiêm phụ thuộc vào các thử nghiệm
- 30. Tiêm phụ thuộc vào thị angularjs sử dụng nguyên cảo
Bạn có thể thêm một số mã mẫu để hiển thị ý của bạn không? – nhaarman