cannot be provided without an @Inject constructor or from an @Provides-annotated method

The error just states that dagger doesn’t have a way to provide said dependency. You will have to add it to your component in some way—and since it is a Fragment—you will have to use a @Module.

I am assuming that your AppComponent is created by your Application on start. Your AppComponent has a lifecycle that is longer than both your activities and fragments lifecycles are. It is therefore reasonable, that it does not know how to provide an activity, or a fragment in your case.

  1. Your DownloadFilePresenterImp depends on your DownloadFileView.
  2. You want to inject DownloadFilePresenterImp into your DownloadFileView
  3. To inject the view and presenter you are using your AppComponent which knows nothing about the activity, and obviously nothing about the fragment. It has a different scope and lifecycle.

To not further cause confusion I will be talking about fragments, since their and the activities lifecycle are what you have to keep in mind. You can just use DownloadFileView with the module, but those long names would get confusing.


To provide a fragment or activity you have to use a module. e.g.

@Module FragmentModule {
    Fragment mFragment;
    FragmentModule(Fragment fragment) { mFragment = fragment; }

    @Provides Fragment provideFragment() { return mFragment; }

    // here you could also provide your view implementation...
    @Provides DownloadFileView provideDownloadFileView() {
        return (DownloadFileView) mFragment;
    }
}

Since this module should only live along with fragments lifecycle, you have to use either subcomponents, or components with a dependency on your AppComponent.

@Component(dependencies=AppComponent.class, modules=FragmentModule.class)
interface FragmentComponent {
    // inject your fragment
    void inject(DownloadFileView fragment);
}

In your fragment you’d have to properly create your component…

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   final View view = inflater.inflate(R.layout.download_file_view, container, false);

   // properly create a component that knows about the fragment
   DaggerFragmentComponent.builder()
           .appComponent(DaggerInjector.getAppComponent())
           .fragmentModule(new FragmentModule(this))
           .build()
           .inject(DownloadFileView.this);

   return view;
}

Also, I highly recommend having a look at and using constructor injection

public class DownloadFilePresenterImp implements DownloadFilePresenterContact {

    @Inject
    public DownloadFilePresenterImp(DownloadFileView downloadFileView) {
        mDownloadFileContract = downloadFileView;
    }
}

Alternatively you can move the provideDownloadfilePresenterImp(View) method to the FragmentModule to have the same effect if you like redundant code.

Done.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)