web-dev-qa-db-ja.com

エラー:[Dagger / MissingBinding] [dagger.Android.AndroidInjector.inject(T)] Dagger

1つのメインアクティビティと複数のフラグメントを含む単純なプロジェクトを作成したいと思います。ここでは、1つのアクティビティに2つのフラグメントがあり、ログインフラグメントにプレゼンターを挿入したいのですが、機能しません。私の間違いはどこにありますか?

MainApplication.Java

public class MainApplication extends DaggerApplication{


private static ApplicationComponent component;
@Override
public void onCreate() {
    super.onCreate();
    Utils.init(this);
}
public static ApplicationComponent getComponent() {
    return component;
}


protected AndroidInjector<? extends DaggerApplication> applicationInjector() 
{
    component = 
    DaggerApplicationComponent.builder().application(this).build();
    component.inject(this);
    return component;
  }


}

MainActivity.Java

public class MainActivity extends DaggerAppCompatActivity  {



private Fragment[] mFragments = new Fragment[2];
private int curIndex;

@Inject
HomeFragment homeFragment;

@Inject
LoginFragment loginFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState != null) {
        curIndex = savedInstanceState.getInt("curIndex");
    }
    mFragments[AppConstant.HOME_FRAGMENT] = homeFragment;
    mFragments[AppConstant.LOGIN_FRAGMENT] = loginFragment;

    FragmentUtils.add(getSupportFragmentManager(), mFragments, 
  R.id.container, curIndex);
    showCurrentFragment(AppConstant.LOGIN_FRAGMENT);
}
private void showCurrentFragment(int index) {
    FragmentUtils.showHide(curIndex = index, mFragments);
}

@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle 
  outPersistentState) {
    super.onSaveInstanceState(outState, outPersistentState);
    outState.putInt("curIndex", curIndex);
  }


 }

ApplicationComponent.Java

@Singleton
@Component(modules = {
    ContextModule.class,
    ApiServiceModule.class,
    AndroidSupportInjectionModule.class,
    ActivityBuilder.class
 })
  public interface ApplicationComponent extends 
         AndroidInjector<DaggerApplication> {

void inject(MainApplication component);

@Component.Builder
interface Builder {

    ApplicationComponent build();

    @BindsInstance
    Builder application(MainApplication application);
}
}

LoginFragment.Java

public class LoginFragment extends DaggerFragment{

View mRootView;


@Inject
HomeFragment homeFragment;


@Inject
LoginContract.Presenter mPresenter;

@Inject
public LoginFragment() {
    // Required empty public constructor
}


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

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    mRootView =inflater.inflate(R.layout.fragment_login, container, false);
    ButterKnife.bind(this,mRootView);
    // Inflate the layout for this fragment
    return mRootView;
}

@OnClick(R.id.button)
public void goToHome(){
    FragmentUtils.replace(this,homeFragment,false);

}

@Override
public void onAttach(Context context) {
    super.onAttach(context);

}

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

     }


  }

ActivityBuilder.Java

@Module
public abstract class ActivityBuilder {

@ContributesAndroidInjector(modules = {MainActivityModule.class , 
FragmentContainerModule.class, AndroidSupportInjectionModule.class} )
abstract MainActivity bindMainActivity();


 }

FragmentContainerModule.Java

@Module
public abstract class FragmentContainerModule {


 @ContributesAndroidInjector(modules = 
             {HomeFragmentModule.class,
              AndroidSupportInjectionModule.class})
abstract HomeFragment contributeHomeFragmentInjector();


@FragmentScope
@ContributesAndroidInjector(modules = 
           {LoginFragmentModule.class,
             AndroidSupportInjectionModule.class})
abstract LoginFragment contributeLoginFragmentInjector();




}

** LoginFragmentModule.Java

@Module
public abstract class LoginFragmentModule {

@FragmentScope
@Binds
public abstract LoginContract.Presenter presenter(LoginPresenter 
      loginPresenter);
}

そしてこれはエラーです:

error: [Dagger/MissingBinding] [dagger.Android.AndroidInjector.inject(T)] 
ir.heart.heartproject.utils.MvpUtils.LoginContract.Presenter cannot be 
provided without an @Provides-annotated method.
A binding with matching key exists in component: 
ir.heart.heartproject.utils.di.
modules.FragmentContainerModule_ContributeLoginFr 
agmentInjector.LoginFragmentSubcomponent
ir.heart.heartproject.utils.MvpUtils.
LoginContract.Presenter is injected at
ir.heart.heartproject.views.fragments.LoginFragment.mPresenter
ir.heart.heartproject.views.fragments.LoginFragment is injected at
ir.heart.heartproject.views.activities.MainActivity.loginFragment
ir.heart.heartproject.views.activities.MainActivity is injected at
dagger.Android.AndroidInjector.inject(T)
component path: 
ir.heart.heartproject.utils.di.component.ApplicationComponent ? 
ir.heart.heartproject.utils.di.modules.
ActivityBuilder_BindMainActivity.MainActivitySubcomponent
4
omid

@injectを使用して、LoginFragmentのコンストラクターに注釈を付けます。新しいインスタンスが要求されると、DaggerはLoginFragmentクラスのインスタンスを構築し、それらの依存関係(mPresenterフィールドなど)を満たします。 MainActivitySubcomponentはLoginFragmentModuleにアクセスしないため、DaggerはLoginContract.Presenterを提供できないエラーを表示します。コンストラクタインジェクションを使用する代わりに、MainActivityにLoginFragmentを提供するために別のアプローチを使用すると、問題は解決されます。 LoginFragmentコンストラクターから@injectを削除し、次の例のように提供するモジュールを作成する必要があります。

@Module
public class MainModule {

    @Provides
    public static LoginFragment provideLoginFragment() {
        return LoginFragment.newInstance("param1", "param2");
    }

}

短剣のヒント:システムがインスタンス化するオブジェクトにコンストラクタインジェクションを使用しないでください。 Androidでは、アクティビティとフラグメントに依存関係を注入するには、フィールド注入アプローチを使用する必要があります。

4
abbas oveissi