9

Câu hỏi của tôi tương tự như this.Chèn phụ thuộc vào CustomView với dao găm 2 (trong phạm vi hoạt động)

Vì vậy, ví dụ, tôi có một thực hiện LiveData:

public class CustomLiveData extends LiveData<SomeEvent> { 

    @Inject 
    public CustomLiveData(@ActivityContext Context context) { 
     //.... 
    } 

} 

mà tôi muốn đưa vào trong một giao diện tùy chỉnh:

public class CustomView extends View { 
    @Inject 
    SomeApplicationProvider anyProvider; 

    @Inject 
    CustomLiveData dataProvider; 
    // Getting @com.di.qualifiers.ActivityContext android.content.Context cannot be provided without an @Provides-annotated method. 
    // @com.di.qualifiers.ActivityContext android.content.Context is injected at com.repositories.CustomLiveData.<init>(context) 
    // com.repositories.CustomLiveData is injected at com.ui.CustomView.dataProvider com.ui.CustomView is injected at 
    // com.di.ApplicationComponent.inject(view) 

    public CustomView(Context context) { this(context, null); } 
    public CustomView(Context AttributeSet attrs) { 
     super(context, attrs); 

     // Works ok for application provider 
     Application.getComponent(context).inject(this); 
    } 
} 

Và đây là phần còn lại của lớp DI:

@ApplicationScope 
@Component(
     modules = {AndroidInjectionModule.class, 
       ActivityBuilder.class 
     }) 

public interface ApplicationComponent extends AndroidInjector<MyApp> { 

    void inject(MyApp application); 

    void inject(CustomView view); 

    @Component.Builder 
    abstract class Builder extends AndroidInjector.Builder<MyApp> { 

     public abstract ApplicationComponent build(); 
    } 
} 

@ActivityScope 
@Module (subcomponents = MainActivitySubcomponent.class) 
public abstract class ActivityBuilder { 

    @Binds 
    @IntoMap 
    @ActivityKey(MainActivity.class) 
    abstract AndroidInjector.Factory<? extends Activity> 
    bindActivityInjectorFactory(MainActivitySubcomponent.Builder builder); 

    //... 

} 


@Subcomponent(modules = {MainActivityModule.class}) 
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> { 

    @Subcomponent.Builder 
    abstract class Builder extends AndroidInjector.Builder<MainActivity> { 

    } 
} 

@ActivityScope 
@Module 
public class MainActivityModule { 

    @Provides 
    @ActivityContext 
    public Context provideActivityContext(MainActivity activity) { 
     return activity; 
    } 

    // Seems to be wrong or not enough!? 
    @Provides 
    public CustomLiveData provideCustomLiveData(@ActivityContext Context context) { 
     return new CustomLiveData(context); 
    } 
} 


@Qualifier 
public @interface ActivityContext{ 
} 

Lưu ý rằng tôi không nhận được bất kỳ khiếu nại trình biên dịch nào nếu CustomLiveData được tiêm vào MainActivity thay vào chế độ xem. Cảm ơn!

+0

Bạn có gặp phải bất kỳ lỗi biên dịch nào khi tiêm 'CustomLiveData' vào chế độ xem' Tùy chỉnh' không? Hãy đăng nó cùng với câu hỏi của bạn. –

+0

thư được đưa vào phần CustomView. Xem "// Getting @ com.di.qualifiers.ActivityContext android.content.Context không thể ....." – sinek

+0

Bạn có thể đăng '@ ActivityContext' không? –

Trả lời

13

tl; dr Đừng tiêm mô hình lớp phụ thuộc bên trong tùy chỉnh View đối tượng

lớp con của View không mục tiêu tốt cho 2 tiêm Dagger. View đối tượng có nghĩa là để được rút ra và không phải khác, do đó tên "xem". Các nhà xây dựng cho View phải làm rõ điều này; chúng được thiết kế để thổi phồng View các đối tượng từ các thuộc tính được chỉ định trong XML. Nói cách khác, một đối tượng View có thể được chỉ định trong tệp layout.xml, được tăng cường tại điểm thích hợp trong vòng đời và sau đó thu được sử dụng findViewById(int id), Butterknife hoặc ràng buộc dữ liệu. Theo cách này, các đối tượng View tùy chỉnh tốt nhất không phụ thuộc.

Nếu bạn muốn liên kết View và một số dữ liệu từ lớp mô hình, mẫu chuẩn là viết Bộ điều hợp giống như cho RecyclerViewListView. Nếu điều này là không thể, bằng cách sử dụng một setter (ví dụ: setData()) là thích hợp hơn để truyền phụ thuộc từ lớp mô hình trong constructor hoặc yêu cầu tiêm từ bên trong một trong các phương pháp vòng đời của View.

Nếu thay vào đó bạn tiêm đối tượng LiveData bên trong Hoạt động hoặc Phân đoạn bằng cách sử dụng lớp AndroidInjector chính xác Context sẽ được cung cấp mà không cần phải làm gì cả. Điều này giải thích bình luận của bạn "Tôi không nhận được bất kỳ khiếu nại trình biên dịch nếu CustomLiveData được tiêm vào MainActivity thay vì vào xem."

Khi bạn đã tiêm đối tượng LiveData vào Hoạt động, hãy sử dụng một trong các phương pháp trên (bộ điều hợp hoặc bộ chuyển đổi) để kết hợp dữ liệu với tùy chỉnh View của bạn.Xem ví dụ Kiến trúc Google Android here nơi các yếu tố từ các lớp mô hình được tiêm sử dụng Dagger 2 và sau đó liên kết với một ListView sử dụng findViewByIdsetAdapter()

Liên kết với các vấn đề Dagger 2 nơi tiêm View đối tượng được thảo luận:

https://github.com/google/dagger/issues/720

1

hệ thống phân cấp Dagger của bạn trông như thế này: appcomponent ->activitycomponent

Bạn cố gắng bơm hoạt động context bên trong xem, mà phụ thuộc vào appcomponent trực tiếp.

Không thể vì không có phương pháp nào có thể cung cấp ngữ cảnh hoạt động trong appcomponent. Thay vào đó, bên trong xem, bạn nên lấy hoạt động (ví dụ sử dụng getContext), trích xuất activitycomponent từ nó và chỉ sau đó tiêm CustomLiveData.

Các vấn đề liên quan