2016-04-25 18 views
8

Tôi mới bắt đầu sử dụng Dagger 2 và tôi tìm thấy hàng ngàn bài hướng dẫn trực tuyến mỗi người với một cách triển khai khác nhau và bây giờ tôi hơi bối rối. Vì vậy, về cơ bản đây là những gì tôi đã viết vào lúc này:Presenter injection with Dagger 2

AppModule.java:

@Module 
public class AppModule { 

Application mApplication; 

public AppModule(Application application) { 
    mApplication = application; 
} 

@Provides 
@Singleton 
Application providesApplication() { 
    return mApplication; 
} 
} 

DataModule.java:

@Module 
public class DataModule { 

private static final String BASE_URL = "http://beta.fridgewizard.com:9001/api/"; 

@Provides 
@Singleton 
NetworkService provideNetworkService() { 
    return new NetworkService(BASE_URL); 
} 

@Provides 
@Singleton 
SharedPreferences provideSharedPreferences(Application app) { 
    return PreferenceManager.getDefaultSharedPreferences(app); 
} 
} 

PrefsModel.java:

@Module(includes = DataModule.class) 
public class PrefsModel { 

@Provides 
@Singleton 
QueryPreferences provideQuery(SharedPreferences prefs) { 
    return new QueryPreferences(prefs); 
} 
} 

AppComponent .java (Tôi đang trưng bày đối tượng QueryPreferences vì ​​tôi cần nó trong một người trình bày, hy vọng là đúng theo cách này):

@Singleton 
@Component(modules = {AppModule.class, DataModule.class, PrefsModel.class}) 
public interface AppComponent { 

    void inject(HomeFragment homeFragment); 

    QueryPreferences preferences(); 
    NetworkService networkService(); 
} 

Sau đó, tôi có FwApplication.java:

public class FwApplication extends Application { 

private static final String TAG = "FwApplication"; 

private NetworkService mNetworkService; 

private AppComponent mDataComponent; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 

     buildComponentAndInject(); 
    } 

    public static AppComponent component(Context context) { 
     return ((FwApplication) context.getApplicationContext()).mDataComponent; 
    } 

    public void buildComponentAndInject() { 
     mDataComponent = DaggerComponentInitializer.init(this); 
    } 

    public static final class DaggerComponentInitializer { 
     public static AppComponent init(FwApplication app) { 
     return DaggerAppComponent.builder() 
       .appModule(new AppModule(app)) 
       .dataModule(new DataModule()) 
       .build(); 
    } 
    } 
} 

Cuối cùng tôi đã thêm một mô-đun cho các diễn giả:

@Module 
public class PresenterModule { 

    @Provides 
    Presenter<FwView> provideHomePresenter(NetworkService networkService) { 
     return new HomePresenterImpl(networkService); 
    } 

    @Provides 
    Presenter<FwView> provideSearchPresenter(NetworkService networkService) { 
     return new SearchPresenterImpl(networkService); 
    } 

} 

Và các thành phần sau đây (trả về lỗi vì tôi không thể thêm phụ thuộc phạm vi tại đây):

@Component(dependencies = AppComponent.class, modules = PresenterModule.class) 
public interface PresenterComponent { 

    void inject(HomePresenterImpl presenter); 
} 

Vì vậy, tôi có vài câu hỏi không rõ ràng cho tôi đọc tài liệu trực tuyến:

  • Làm thế nào tôi có thể sửa chữa các lỗi trong phần dẫn chương trình vì nó phụ thuộc vào NetworkService mà là một singleton được định nghĩa trong AppComponent?
  • Tôi có một HomeFragment mà nên thực hiện HomePresenter với "HomePresenter mới (NetworkService)", nhưng bây giờ tôi không biết làm thế nào để sử dụng DI định nghĩa

EDIT - FIX:

HomeFragment java:

public class HomeFragment extends Fragment { 

private static final String TAG = "FW.HomeFragment"; 


@Inject 
HomePresenterImpl mHomePresenter; 

public static HomeFragment newInstance() { 
    return new HomeFragment(); 
} 

@Override 
public void onCreate(@Nullable Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    FwApplication.component(getActivity()).inject(this); 
} 

Sau đó, tôi sửa đổi các nhà xây dựng người dẫn chương trình theo cách này:

@Inject 
public HomePresenterImpl(NetworkService networkService) { 
    mNetworkService = networkService; 
    mInteractor = new InteractorImpl(mNetworkService); 
} 

Sau đó, NetworkService được tự động tiêm.

Tôi đã tự hỏi nếu nó là đúng theo cách này vì tôi phải gọi cho mỗi mảnh Tôi có cần một người dẫn chương trình được xây dựng theo cách giống như một ở trên đoạn mã sau:

FwApplication.component(getActivity()).inject(this); 
+0

'sửa lỗi trong thành phần trình bày' vui lòng * luôn * bao gồm lỗi –

+1

' '' getAactivity() '' 'được sử dụng trong' '' onCreate() '' 'có thể sinh ra' '' NullPointerException'''. http://stackoverflow.com/a/6225044/1888738 – Bresiu

Trả lời

11

Bạn đang trộn lẫn lên. Để cung cấp cho người trình bày của bạn, bạn nên chuyển sang nội dung như sau:

Sử dụng phép xây dựng nếu có thể.Nó sẽ làm cho mọi việc dễ dàng hơn nhiều

public class HomePresenterImpl { 

    @Inject 
    public HomePresenterImpl(NetworkService networkService) { 
     // ... 
    } 

} 

Để cung cấp việc sử dụng giao diện constructor injecetion này và phụ thuộc về việc thực hiện

Presenter<FwView> provideHomePresenter(HomePresenterImpl homePresenter) { 
    return homePresenter; 
} 

Bằng cách này bạn không cần phải gọi cho bất kỳ nhà xây dựng cho mình. Và để thực sự tiêm người dẫn chương trình ...

public class MyFragment extends Fragment { 

    @Inject 
    Presenter<FwView> mHomePresenter; 

    public void onCreate(Bundle xxx) { 
     // simplified. Add your modules/Singleton component 
     PresenterComponent component = DaggerPresenterComponent.create().inject(this); 
    } 
} 

Bằng cách này bạn sẽ bơm những điều. Vui lòng đọc kỹ điều này và cố gắng hiểu nó. Điều này sẽ khắc phục vấn đề lớn, bạn vẫn không thể cung cấp 2 thuyết trình cùng loại từ các module tương tự (trong phạm vi tương tự)

// DON'T 
@Provides 
Presenter<FwView> provideHomePresenter(NetworkService networkService) { /**/ } 

@Provides 
Presenter<FwView> provideSearchPresenter(NetworkService networkService) { /**/ } 

này sẽ không làm việc. Bạn không thể cung cấp 2 đối tượng cùng loại. Họ không thể phân biệt được. Hãy xem @Qualifiers như @Named nếu bạn chắc chắn đây là cách bạn muốn.

+0

Cảm ơn bạn rất nhiều vì đã trả lời, tôi đã chỉnh sửa câu hỏi để cho thấy cách tôi sửa nó theo lời khuyên của bạn. (Tôi không chắc chắn về cách tôi đã thực hiện tiêm Presenter trong đoạn) – user1341300

+2

@David cho 'return homePresenter;' bạn có thể sử dụng chú thích '@ Binds', có thể tạo ra mã tốt hơn đằng sau hậu trường. Xem https://google.github.io/dagger/faq.html#binds và https://google.github.io/dagger/api/latest/dagger/Binds.html – TWiStErRob

+0

Cảm ơn bạn rất nhiều! Tôi cũng đang vật lộn với bản thân mình. Điều này xóa một số nghi ngờ của tôi. Cám ơn bạn một lần nữa. – taitasciore

4

Bạn không phải cung cấp Chú thích nếu chú thích @Inject được sử dụng trong hàm tạo. Chú thích @Inject được sử dụng trong hàm tạo của lớp làm cho lớp đó trở thành một phần của biểu đồ phụ thuộc. Vì vậy, nó cũng có thể được tiêm khi cần thiết.

Mặt khác, nếu bạn thêm chú thích @Inject vào trường, nhưng không phải cho các hàm tạo, bạn phải cung cấp lớp đó.

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