2015-04-23 37 views
7

Tôi có thiết lập thử nghiệm Dagger 2 đơn giản, dựa trên http://konmik.github.io/snorkeling-with-dagger-2.html. Nó tiêm một PreferenceLogger mà kết quả đầu ra tất cả các sở thích. Trong lớp được tiêm, tôi có thể @Inject thêm các lớp.Dagger 2 và triển khai giao diện

public class MainActivity extends Activity { 
    @Inject PreferencesLogger logger; 
    @Inject MainPresenter presenter; 

    @Override protected void onCreate(Bundle savedInstanceState) { 
    MyApplication.getComponent().inject(this); 
    presenter.doStuff(); 
     logger.log(this); 
    } 
} 


public class PreferencesLogger { 

    @Inject OkHttpClient client; 
    @Inject public PreferencesLogger() {} 

    public void log(Contect context) { 
    // this.client is available 
    } 
} 

Khi tôi chạy điều này, bộ ghi nhật ký được đặt và bên trong PreferencesLogger.log OkHttpClient được đặt chính xác. Vì vậy, ví dụ này hoạt động như mong đợi. Bây giờ tôi đang cố gắng để có được một cấu trúc MVP tại chỗ. Có giao diện MainPresenter với triển khai. Trong MainActivity tôi đặt một:

@Inject MainPresenter presenter; 

vì vậy tôi có thể chuyển đổi MainPresenter này bằng cách thực hiện thay thế (gỡ lỗi hoặc kiểm tra). Ofcourse, bây giờ tôi cần một Module để xác định những gì thực hiện tôi muốn sử dụng.

public interface MainPresenter { 
    void doStuff(); 
} 

public class MainPresenterImpl implements MainPresenter { 

    @Inject OkHttpClient client; 

    public MainPresenterImpl() {} 

    @Override public void doStuff() { 
    // this.client is not available  
    } 
} 


@Module public class MainActivityModule { 
    @Provides MainPresenter provideMainPresenter() { 
     return new MainPresenterImpl(); 
    } 
} 

Hiện tại, OkHttpClient không được tiêm thêm nữa. Ofcourse tôi có thể thay đổi các mô-đun để chấp nhận một tham số OkHttpClient, nhưng tôi không nghĩ rằng đây là cách đề nghị để làm điều đó. Có một lý do tại sao MainPresenterImpl không bơm đúng cách?

+0

Tôi hỏi một câu hỏi liên quan ở đây: http://stackoverflow.com/questions/30555285/dagger2-injecting-implementation-classes-with-component – EpicPandaForce

+0

hãy xem bài viết và mẫu dự án này mà có thể giúp: https://medium.com/@m_mirhoseini/yet-another-mvp-article-part-1-lets-get-to-know-the-project-d3fd553b3e21#.6y9ze7e55 –

Trả lời

4

Không giống như với việc xây dựng, @Inject trường chú thích của phụ thuộc được xây dựng trong @Provides phương pháp không thể được tự động tiêm. Việc có thể chèn các trường yêu cầu một thành phần cung cấp loại trường trong các mô-đun của nó và trong chính các phương thức của nhà cung cấp, việc triển khai đó không có sẵn.

Khi trường presenter được tiêm vào MainActivity, tất cả những gì xảy ra là phương thức của nhà cung cấp được gọi và presenter được đặt thành giá trị trả về. Trong ví dụ của bạn, hàm tạo no-args không khởi tạo, và cũng không phải phương thức của nhà cung cấp, do đó không có khởi tạo nào diễn ra.

Tuy nhiên, phương pháp nhà cung cấp có quyền truy cập vào các phiên bản của các loại khác được cung cấp trong mô-đun thông qua các tham số của nó. Tôi nghĩ rằng việc sử dụng các tham số trong phương thức nhà cung cấp thực tế là cách để "tiêm" các phụ thuộc của kiểu được cung cấp, bởi vì nó chỉ rõ chúng là phụ thuộc trong mô-đun, cho phép Dagger ném lỗi - nếu họ không thể thỏa mãn.

Lý do nó không hiện ném ra một lỗi là vì MainPresenterImplthể được OkHttpClient sự phụ thuộc của nó thỏa mãn nếu MainPresenterImpl và không MainPresenter đang ở đâu đó một mục tiêu cho tiêm. Dagger không thể thực hiện một phương thức tiêm thành viên cho kiểu giao diện, bởi vì như một giao diện, nó không thể có các trường tiêm, và nó sẽ không tự động tiêm các trường của kiểu triển khai thực hiện, vì nó chỉ cung cấp bất cứ phương thức nào của nhà cung cấp trả về.

4

Bạn có thể tiêm MainPresenterImpl bằng cách sử dụng chức năng tiêm xây dựng.

/* unscoped */ 
public class MainPresenterImpl implements MainPresenter { 

    @Inject 
    OkHttpClient client; 

    @Inject 
    public MainPresenterImpl() { 
    } 

    @Override public void doStuff() { 
     // this.client is now available! :) 
    } 
} 


@Module 
public class AppModule { 
    private MyApplication application; 

    public AppModule(MyApplication application) { 
     this.application = application; 
    } 

    @Provides 
    /* unscoped */ 
    public MyApplication application() { 
     return application; 
    } 
} 

@Module 
public abstract class MainActivityModule { 
    @Binds public abstract MainPresenter mainPresenter(MainPresenterImpl mainPresenterImpl); 
} 
Các vấn đề liên quan