Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AndroidInjector<android.app.Activity> cannot be provided without an @Provides- or @Produces-annotated method

I'm getting the error while trying to get the new Android dagger classes from Dagger v2.11 working in our project. I'm not exactly sure what the problem is, as I've taken into account the Android documentation over at https://google.github.io/dagger//android.html and still cannot get over this issue. Any ideas on what's wrong with this setup?

MyApplication:

public class MyApplication extends Application implements HasActivityInjector
{
    @Inject
    AndroidInjector<Activity> androidInjector;

    @Override
    public void onCreate()
    {
        super.onCreate();
        AppInjector.init(this);
    }

    @Override
    public AndroidInjector<Activity> activityInjector()
    {
        return androidInjector;
    }
}

AppComponent:

@Singleton
@Component(modules = {
        AndroidSupportInjectionModule.class,
        AppModule.class,
        ActivityModule.class,
})
public interface AppComponent
{
    @Component.Builder
    interface Builder
    {
        @BindsInstance
        Builder application(Application application);

        AppComponent build();
    }

    void inject(MyApplication myApplication);
}

ActivityModule:

@Module
abstract class ActivityModule
{
    @ContributesAndroidInjector(modules = FragmentModule.class)
    abstract MainActivity contributeMainActivity();

    // all other activities defined as above
}

FragmentModule:

@Module
abstract class FragmentModule
{
    @ContributesAndroidInjector
    abstract MyFragment contributeMyFragment();
}

AppInjector:

 public static void init(MyApplication myApplication)
    {
        DaggerAppComponent.builder().application(myApplication)
                          .build().inject(myApplication);
        myApplication
                .registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks()
                {
                    @Override
                    public void onActivityCreated(Activity activity, Bundle savedInstanceState)
                    {
                        handleActivity(activity);
                    }

                    @Override
                    public void onActivityStarted(Activity activity)
                    {

                    }

                    @Override
                    public void onActivityResumed(Activity activity)
                    {

                    }

                    @Override
                    public void onActivityPaused(Activity activity)
                    {

                    }

                    @Override
                    public void onActivityStopped(Activity activity)
                    {

                    }

                    @Override
                    public void onActivitySaveInstanceState(Activity activity, Bundle outState)
                    {

                    }

                    @Override
                    public void onActivityDestroyed(Activity activity)
                    {

                    }
                });
    }

    private static void handleActivity(Activity activity)
    {
        if (activity instanceof HasSupportFragmentInjector)
        {
            AndroidInjection.inject(activity);
        }
        if (activity instanceof FragmentActivity)
        {
            ((FragmentActivity) activity).getSupportFragmentManager()
                                         .registerFragmentLifecycleCallbacks(
                                                 new FragmentManager.FragmentLifecycleCallbacks()
                                                 {
                                                     @Override
                                                     public void onFragmentCreated(FragmentManager fm, Fragment f,
                                                                                   Bundle savedInstanceState)
                                                     {
                                                         if (f instanceof Injectable)
                                                         {
                                                             AndroidSupportInjection.inject(f);
                                                         }
                                                     }
                                                 }, true);
        }
    }

AppModule:

@Module(includes = ViewModelModule.class)
class AppModule
{
    @Singleton
    @Provides
    UserDao provideUserDao(MyDatabase db)
    {
        return db.userDao();
    }

    // all other DAOs
}

ViewModelModule:

@Module
abstract class ViewModelModule
{
    @Binds
    @IntoMap
    @ViewModelKey(UserViewModel.class)
    abstract ViewModel bindUserViewModel(UserViewModel userViewModel);
}

MainActivity:

public class MainActivity extends AppCompatActivity implements HasSupportFragmentInjector
{
     @Inject
    AndroidInjector<Fragment> androidInjector;

    @Override
    public AndroidInjector<Fragment> supportFragmentInjector()
    {
        return androidInjector;
    }
}

Stack trace:

Error:(29, 10) error: dagger.android.AndroidInjector<android.app.Activity> cannot be provided without an @Provides- or @Produces-annotated method.
dagger.android.AndroidInjector<android.app.Activity> is injected at
com.myapp.MyApplication.androidInjector
com.myapp.MyApplication is injected at
com.myapp.dagger.AppComponent.inject(myApplication)
like image 626
Bogdan Zurac Avatar asked Jul 02 '17 08:07

Bogdan Zurac


People also ask

Can [dagger / missingbinding] be provided without an @ provides-annotated method?

The project being centered on the use of the framework Dagger to design this architecture, we found the error message: [Dagger / MissingBinding] cannot be provided without an @ Provides-annotated method. After several unsuccessful searches on Internet, we investigated with brute force. Here is what we found.

How do I inject an object into an appmodule?

If you want to inject an object that you build at runtime, the only way to go is to pass that object to the AppComponent. In your case it could be: @Singleton @Component (modules = AppModule.class) public interface AppComponent { void inject (DownloadFileView target); }

Is it OK to use activity inject view in fragment?

Like you said, the Activity inject View is ok. but in the fragment, it was compile error, i don't know why? Sorry, something went wrong. i didn't get chance to get deeper into this issue.


1 Answers

Try to replace AndroidInjector to DispatchingAndroidInjector of your androidInjector variable. That's work for me. Here is mine ( kotlin)

class PodcastApp : Application(), HasActivityInjector {

@Inject
lateinit var dispatchingAndroidInjector : DispatchingAndroidInjector<Activity>


companion object {
    lateinit var instance: PodcastApp
}


override fun onCreate() {
    super.onCreate()

    instance = this
    FirebaseApp.initializeApp(this)

    if (BuildConfig.DEBUG) {
        Timber.plant(Timber.DebugTree())
        Stetho.initializeWithDefaults(this)

        AppInjector.init(this)
    }
}

override fun activityInjector(): AndroidInjector<Activity> {
    return dispatchingAndroidInjector
}

}

like image 200
Son Tieu Avatar answered Nov 15 '22 07:11

Son Tieu