Dagger2构造函数注入不起作用

时间:2017-06-24 14:50:11

标签: java android dagger

我正在尝试通过构造函数注入为Fragment注入一个演示者(这样我就不需要为演示者创建@Provides方法了。)

我相信我正确地做到了,但我仍然收到以下错误:

如果没有@ Provide-或@ Produces-annotation方法,则无法提供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 个答案:

答案 0 :(得分: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);
}

现在,由于您的模块没有构造函数,因此不需要为Dagger提供实例,因此您可以像这样构造组件:

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