2017-06-24 207 views
0

我想通过构造函数注入为我的Fragment注入一个演示者(这样我就不需要为演示者创建一个@Provides方法)。Dagger2构造函数注入不工作

我相信,我在做正确,但我仍收到以下错误:没有@规定外或@主要生产的注释方法不能提供

MainFragmentPresenter。

这里是我的设置:

ApplicationComponent.java

@Singleton 
@Component(
     modules = { 
       NetworkModule.class 
     } 
) 
public interface ApplicationComponent { 

    NetworkService networkService(); 
} 

MainFragmentComponent.java

@PerFragment 
@Component(
     dependencies = ApplicationComponent.class, 
     modules = MainFragmentPresenterModule.class 
) 
public interface MainFragmentComponent { 

    MainFragmentView view(); 

    void inject(MainFragment mainFragment); 
} 

MainFragmentPresenterModule.java

@Module 
public class MainFragmentPresenterModule { 

    private final MainFragmentView _view; 

    public MainFragmentPresenterModule(MainFragmentView view) { 
     _view = view; 
    } 

    @Provides 
    @PerFragment 
    MainFragmentView provideMainFragmentView() { 
     return _view; 
    } 
} 

NetworkModule.java

@Module 
public class NetworkModule { 

    @Provides 
    @Singleton 
    OkHttpClient provide_OkHttpClient() { 
     return new OkHttpClient(); 
    } 

    @Provides 
    @Singleton 
    OpenWeatherEndpoints provide_OpenWeatherAPI(OkHttpClient client) { 

     Retrofit retrofit = new Retrofit.Builder() 
       .baseUrl("http://api.openweathermap.org/data/2.5/") 
       .addConverterFactory(GsonConverterFactory.create()) 
       .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 
       .client(client) 
       .build(); 

     return retrofit.create(OpenWeatherEndpoints.class); 

    } 

    @Provides 
    @Singleton 
    YoutubeEndpoints provide_YoutubeEndpoints(OkHttpClient client) { 

     Retrofit retrofit = new Retrofit.Builder() 
       .baseUrl("https://www.googleapis.com/youtube/v3/") 
       .addConverterFactory(GsonConverterFactory.create()) 
       .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 
       .client(client) 
       .build(); 

     return retrofit.create(YoutubeEndpoints.class); 

    } 

    @Provides 
    @Singleton 
    NetworkService provide_NetworkService(OpenWeatherEndpoints openWeatherEndpoints, YoutubeEndpoints youtubeEndpoints) { 
     return new NetworkService(openWeatherEndpoints, youtubeEndpoints); 
    } 
} 

PerFragment.java

@Scope 
@Retention(RUNTIME) 
@interface PerFragment { 
} 

MainFragmentPresenterImpl.java

public class MainFragmentPresenterImpl implements MainFragmentPresenter { 
    private final MainFragmentView _view; 
    private NetworkService _service; 

    @Inject MainFragmentPresenterImpl(MainFragmentView view, NetworkService networkService) { 
     _view = view; 
     _service = networkService; 
    } 
} 

,当我尝试在我的片段注入演示...

public class MainFragment extends Fragment implements MainFragmentView { 

    public static final String TAG = "MainFragment"; 

    @Inject 
    MainFragmentPresenter _presenter; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     DaggerMainFragmentComponent.builder() 
       .applicationComponent(WeatherForecastApp.get(getContext()).getAppComponent()) 
       .mainFragmentPresenterModule(new MainFragmentPresenterModule(this)) 
       .build() 
       .inject(this); 
    } 
} 

所有帮助是非常感谢!谢谢。

回答

1

您需要添加从MainFragmentPresenterImpl到MainFragmentPresenter的绑定。 Dagger不会在类型之间进行转换,因此您需要使用@Binds方法明确执行此操作。 @Binds相当于一个@Provides方法,它只是返回它的参数,但它的实现效率更高。只要改变你的模块是这样的:

@Module 
public abstract class MainFragmentPresenterModule { 
    ... 
    @Binds 
    abstract MainFragmentPresenter(MainFragmentPresenterImpl impl); 
} 

此外,还可以通过使用@BindsInstance摆脱@Provides方法,_view场和构造的模块中。现在

public interface MainFragmentComponent { 
    @Component.Builder 
    interface Builder { 
     @BindsInstance 
     Builder mainFragmentView(MainFragmentView mainFragmentView); 
    } 
    void inject(MainFragment mainFragment); 
} 

,因为你对你的模块没有一个构造函数,匕首并不需要提供一个实例,这样你就可以构建这样的组件:

DaggerMainFragmentComponent.builder() 
    .applicationComponent(WeatherForecastApp.get(getContext()).getAppComponent()) 
    .mainFragmentView(this) 
    .build() 
    .inject(this);