如何使用Dagger2将Presenter注入Fragment?

时间:2017-07-29 15:56:39

标签: android dagger-2 android-mvp

我有RegisterPresenterImpl,我想注入片段。当我调用该演示者的方法register()时,我的应用程序崩溃。它说我的演示者为空。

我如何解决这个问题?

public class RegisterAccountFragment extends Fragment implements RegisterAccountView {


@Inject
RegisterAccountPresenterImpl registerPresenter;

public RegisterAccountFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v =  inflater.inflate(R.layout.fragment_register_account, container, false);

 DaggerRegisterAccountComponent.builder()
            .netComponent(((App) getActivity().getApplicationContext()).getNetComponent())
            .registerAccountModule(new RegisterAccountModule(this))
            .build()
            .inject(this);

   registerPresenter.register(getName(), getEmail(), getPassword(), getConfirm());
     } 
}

组件界面:

 @FragmentScoped
 @Component(dependencies = NetComponent.class, modules =  RegisterAccountModule.class)
  public interface RegisterAccountComponent {
       void inject(RegisterAccountFragment fragment);
}

这是模块类:

@Module
public class RegisterAccountModule {

private RegisterAccountView view;

public RegisterAccountModule(RegisterAccountView view){
    this.view = view;
}


@Provides
@FragmentScoped
RegisterAccountView providesRegisterAccountView(){
    return view;
   }
}

这是名为RegisterPresenterImpl的类

 public class RegisterAccountPresenterImpl implements RegisterAccountPresenter{

private RegisterAccountView view;
private Retrofit retrofit;
private CompositeDisposable compositeDisposable = new CompositeDisposable();

@Inject
public RegisterAccountPresenterImpl(Retrofit retrofit, RegisterAccountView view){
    this.retrofit = retrofit;
    this.view = view;
}

@Override
public void register(String name, String email, String password, String confirm) {
    // CODE
    }
}

2 个答案:

答案 0 :(得分:3)

RegisterAccountPresenterImpl

中提供您的RegisterAccountComponent

应该是这样的:

@FragmentScoped
@Component(dependencies = NetComponent.class, modules =  
RegisterAccountModule.class)
public interface RegisterAccountComponent {
   void inject(RegisterAccountFragment fragment);

   RegisterAccountPresenterImpl getRegisterAccountPresenterImlp();
}

您的实施有一些内容

  1. Inject Constructor/Field/Method尚未支持public。删除冗余关键字
  2. DaggerRegisterAccountComponent而不是onCreate()中初始化onCreateView(),以确保在使用任何依赖项之前构建它。
  3. 考虑将final用于构造函数内设置的field中的所有RegisterAccountPresenterImpl。因为它只会初始化一次。
  4. private final RegisterAccountView view;
    
    private final Retrofit retrofit;
    
    1. 我只是不明白为什么你必须在view内定义presenter(这是你的片段),反之亦然。这是循环依赖吗?
    2. 我发现这个tutorial是关于使用MVP和Dagger的超酷帖子。请考虑阅读

      还有一件事:如果你想有效地调试Dagger-2,请转到你的Dagger...Component类来查看那里构建的内容。 Android Studio将帮助您在使用时发现任何问题。

      希望这有帮助!

答案 1 :(得分:2)

应该是

public class RegisterAccountFragment extends Fragment implements RegisterAccountView {       
    @Inject
    RegisterAccountPresenter registerPresenter; // <-- not impl, why use DI then?

@FragmentScoped // <-- scope here
public class RegisterAccountPresenterImpl implements RegisterAccountPresenter{

    private final RegisterAccountView view;
    private final Retrofit retrofit;

    @Inject
    public RegisterAccountPresenterImpl(Retrofit retrofit, RegisterAccountView view){
        this.retrofit = retrofit;
        this.view = view;
    }
}

@Module
public class RegisterAccountModule {

    private RegisterAccountView view;

    public RegisterAccountModule(RegisterAccountView view){
        this.view = view;
    }

    @Provides
    // @FragmentScoped // <-- no need for scoping item in module
    RegisterAccountView providesRegisterAccountView(){
        return view;
    }

    @Provides // <-- provide constructor injected stuff and bind to interface
    RegisterAccountPresenter registerAccountPresenter(RegisterAccountPresenterImpl impl) {
        return impl;
    }
}