android - MVVM Dagger2 A Binding With Matching Key Exists in Component -


i using following google sample project: https://github.com/googlesamples/android-architecture-components reference new project , having difficulties trying add second activity project.

here error when compiling

error:(22, 8) error: [dagger.android.androidinjector.inject(t)] com.apps.myapp.ui.common.mainactivity cannot provided without @inject constructor or @provides-annotated method. type supports members injection cannot implicitly provided. com.apps.myapp.ui.common.mainactivity injected @ com.apps.myapp.ui.common.navigationcontroller.<init>(mainactivity) com.apps.myapp.ui.common.navigationcontroller injected @ com.apps.myapp.ui.addcontacts.addcontactsfragment.navigationcontroller com.apps.myapp.ui.addcontacts.addcontactsfragment injected @ dagger.android.androidinjector.inject(arg0) binding matching key exists in component: com.apps.myapp.di.activitymodule_contributemainactivity.mainactivitysubcomponent 

here code

activitymodule

@module public abstract class activitymodule {      @contributesandroidinjector(modules = fragmentbuildersmodule.class)     abstract mainactivity contributemainactivity();      @contributesandroidinjector(modules = fragmentbuildersmodule.class)     abstract contactactivity contributecontactactivity(); }  

appcomponent

@singleton @component(modules = {         androidinjectionmodule.class,         appmodule.class,         activitymodule.class}) public interface appcomponent {     @component.builder     interface builder {         @bindsinstance builder application(application application);         appcomponent build();     }     void inject(app app); } 

appinjector

public class appinjector {     private appinjector() {}     public static void init(app app) {daggerappcomponent.builder().application(app).build().inject(app);                     app.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     bnderapiservice provideservice() {         return new retrofit.builder()                 .baseurl("serverurl")                 .addconverterfactory(gsonconverterfactory.create())                 .addcalladapterfactory(new livedatacalladapterfactory())                 .build()                 .create(apiservice.class);     }      @singleton @provides     db providedb(application app) {         return room.databasebuilder(app, db.class,"db.db").build();     }      @singleton @provides     userdao provideuserdao(db db) {         return db.userdao();     }      @singleton @provides     contactdao providecontactdao(db db) {         return db.contactdao();     } } 

fragmentbuildersmodule

@module public abstract class fragmentbuildersmodule {      @contributesandroidinjector     abstract addcontactsfragment contributeadduserfragment();      @contributesandroidinjector     abstract contactsfragment contributecontactsfragment();      @contributesandroidinjector     abstract chalkboardfragment contributechalkboardfragment(); } 

injectable

public interface injectable { } 

viewmodelkey

@documented @target({elementtype.method}) @retention(retentionpolicy.runtime) @mapkey @interface viewmodelkey {     class<? extends viewmodel> value(); } 

viewmodelmodule

@module abstract class viewmodelmodule {     @binds     @intomap     @viewmodelkey(addcontactsviewmodel.class)     abstract viewmodel bindaddcontactsviewmodel(addcontactsviewmodel addcontactsviewmodel);      @binds     @intomap     @viewmodelkey(contactsviewmodel.class)     abstract viewmodel bindcontactsviewmodel(contactsviewmodel contactsviewmodel);      @binds     @intomap     @viewmodelkey(chalkboardviewmodel.class)     abstract viewmodel bindchalkboardviewmodel(chalkboardviewmodel chalkboardviewmodel);      @binds     abstract viewmodelprovider.factory bindviewmodelfactory(viewmodelfactory factory); } 

application

public class app extends application implements hasactivityinjector {      @inject     dispatchingandroidinjector<activity> dispatchingandroidinjector;     @override     protected void attachbasecontext(context base) {         super.attachbasecontext(base);         multidex.install(this);     }     @override     public void oncreate() {         super.oncreate();         if (buildconfig.debug) {          }         appinjector.init(this);     }      @override     public dispatchingandroidinjector<activity> activityinjector() {         return dispatchingandroidinjector;     } } 

navigationcontroller

public class navigationcontroller {     private final int containerid;     private final fragmentmanager fragmentmanager;     @inject     public navigationcontroller(mainactivity mainactivity) {         this.containerid = r.id.container;         this.fragmentmanager = mainactivity.getsupportfragmentmanager();     }      public void navigatetousers() {         log.i("tag", "navigate users");         string tag = "users";         addcontactsfragment userfragment = addcontactsfragment.create();         fragmentmanager.begintransaction()                 .replace(containerid, userfragment, tag)                 .addtobackstack(null)                 .commitallowingstateloss();     }      public void navigatetocontacts() {         log.i("tag", "navigate contacts");         string tag = "contacts";         contactsfragment contactsfragment = contactsfragment.create();         fragmentmanager.begintransaction()                 .add(contactsfragment, tag)                 .addtobackstack(null)                 .commitallowingstateloss();     }      public void navigatetochalkboard() {         log.i("tag", "navigate chalkboard");         string tag = "chalkboard";         chalkboardfragment chalkboardfragment = chalkboardfragment.create();         fragmentmanager.begintransaction()                 .add(chalkboardfragment, tag)                 .addtobackstack(null)                 .commitallowingstateloss();     } } 

mainactivity

public class mainactivity extends appcompatactivity implements lifecycleregistryowner, hassupportfragmentinjector {     private final lifecycleregistry lifecycleregistry = new lifecycleregistry(this);     @inject     dispatchingandroidinjector<fragment> dispatchingandroidinjector;     @inject     navigationcontroller navigationcontroller;     private toolbar toolbar;     @override     public lifecycleregistry getlifecycle() {         return lifecycleregistry;     }      @override     protected void oncreate(@nullable bundle savedinstancestate) {         super.oncreate(savedinstancestate);         activitymainbinding binding = databindingutil.setcontentview(this, r.layout.activity_main);         binding.sethandler(this);         binding.setmanager(getsupportfragmentmanager());         toolbar = (toolbar) findviewbyid(r.id.toolbar);         setsupportactionbar(toolbar);     }      @override     public dispatchingandroidinjector<fragment> supportfragmentinjector() {         return dispatchingandroidinjector;     }      static class viewpageradapter extends fragmentpageradapter {         private final list<fragment> mfragmentlist = new arraylist<>();         private final list<string> mfragmenttitlelist = new arraylist<>();          public viewpageradapter(fragmentmanager manager) {             super(manager);         }          @override         public fragment getitem(int position) {             return mfragmentlist.get(position);         }          @override         public int getcount() {             return mfragmentlist.size();         }          public void addfragment(fragment fragment, string title) {             mfragmentlist.add(fragment);             mfragmenttitlelist.add(title);         }          @override         public charsequence getpagetitle(int position) {             return mfragmenttitlelist.get(position);         }     }      @bindingadapter({"handler"})     public static void bindviewpageradapter(final viewpager view, final mainactivity activity) {         final viewpageradapter adapter = new viewpageradapter(activity.getsupportfragmentmanager());         adapter.addfragment(new chalkboardfragment(), "chalkboard");         adapter.addfragment(new contactsfragment(), "contacts");         view.setadapter(adapter);     }      @bindingadapter({"pager"})     public static void bindviewpagertabs(final tablayout view, final viewpager pagerview) {         view.setupwithviewpager(pagerview, true);     } } 

contactactivity

public class contactactivity extends appcompatactivity implements lifecycleregistryowner, hassupportfragmentinjector {     private final lifecycleregistry lifecycleregistry = new lifecycleregistry(this);     @inject     dispatchingandroidinjector<fragment> dispatchingandroidinjector;     @override     public lifecycleregistry getlifecycle() {         return lifecycleregistry;     }      @override     protected void oncreate(@nullable bundle savedinstancestate) {         super.oncreate(savedinstancestate);         setcontentview(r.layout.activity_contact);         if (savedinstancestate == null) {          }     }      @override     public dispatchingandroidinjector<fragment> supportfragmentinjector() {         return dispatchingandroidinjector;     } } 

the example on basing project on says in notes:

an advanced sample uses architecture components, dagger , github api. requires android studio 3.0 canary 1

the way learn new technology start simple, toy-like examples , gradually move way more complex examples once clear on basic concepts. there no need embarassed starting simple. has added advantage of being easy request if goes wrong since example minimal.

in particular case, error getting can reproduced by:

  1. cloning project github

    git clone https://github.com/googlesamples/android-architecture-components.git` 
  2. copy-pasting mainactivity new file contactsactivity

  3. modifying mainactivitymodule activitymodule

so can conclude activitymodule problematic. @contributesandroidinjector not simple might seem. means creating new dagger 2 subcomponent activity specify there (see docs here).

a subcomponent can use bindings parent component not sibling components. 2 lines contributesandroidinjector in activitymodule create 2 sibling subcomponents: 1 mainactivity , 1 contactsactivity.

however, navigationcontroller dependent on mainactivity bound in object graph mainactivity subcomponent not in contactsactivity subcomponent. addcontactsfragment has become part of object graph contactsactivity subcomponent , doesn't have access mainactivity anymore. means when dagger 2 tries inject navigationcontroller inside addcontactsfragment cannot provide mainactivity dependency it. explains "cannot provide" part of error message.

although can't provide mainactivity in particular object graph, androidinjector does know in general mainactivity hence error message "a binding key exists". binding key this? key binds mainactivity.class mainactivityfactory. key bound? in activitymodule when wrote @contributesandroidinjector mainactivity.

how fix getting beyond scope of stackoverflow question because involves lengthy refactor of code. need re-organise object graph navigationcontroller no longer depends on mainactivity. perhaps make depend on appcompatactivity since superclass of both activities. need stop using contributesandroidinjector , write explicit modules 2 activities include bindings appcompatactivity.

however, please go basics , start easier. recipe disaster start complex project without complete understanding , modify hoping work.

the codepath dagger 2 tutorial project easier understand , familiar basic concepts involved in dagger 2. once comfortable basic concepts , have understood dependent components , sub-components, can attempt more difficult example. luck!


Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -