java - Field not injected in Android Dagger project -
i playing dagger on android. created model userpreference
, module called preferencemodule
, class userpreferencetest
test of preferencemodule
. have below 3 java files
userpreference.java
package com.sigicn.preference; import javax.inject.inject; import com.sigicn.commonmodels.application; public class userpreference { public string name, weiboaccount; @inject public application[] frequentlyusedapps; }
then preferencemodule.java
package com.sigicn.preference; import javax.inject.singleton; import com.sigicn.commonmodels.application; import com.sigicn.utils.miscutils; import dagger.module; import dagger.provides; @module(library = true, complete = true) public class preferencemodule { @provides @singleton userpreference provideuserpreference() { userpreference userpreference = new userpreference(); userpreference.frequentlyusedapps = provideapplications(); return userpreference; } @provides @singleton application[] provideapplications() { return new application[]{ new application( miscutils.generateuuid(), "youtube"), new application( miscutils.generateuuid(), "pixi") }; } }
then userpreferencetest.java
package com.sigicn.test.preference; import javax.inject.inject; import com.sigicn.preference.preferencemodule; import com.sigicn.preference.userpreference; import dagger.module; import dagger.objectgraph; import android.test.androidtestcase; public class userpreferencetest extends androidtestcase { @module(injects = {userpreference.class, userpreferencetest.class}, includes = preferencemodule.class) static class testmodule { } objectgraph objectgraph; @inject userpreference userpreference; @override protected void setup() throws exception { if (objectgraph == null) { objectgraph = objectgraph.create(new testmodule()); } super.setup(); } public void testfrequentlyusedapps() { userpreference localuserpreference = objectgraph.get(userpreference.class); assertnotnull(localuserpreference); assertequals(localuserpreference.frequentlyusedapps.length, 2); objectgraph.inject(this); assertnotnull(userpreference); assertequals(userpreference.frequentlyusedapps.length, 2); assertsame(localuserpreference, userpreference); assertsame(localuserpreference.frequentlyusedapps, userpreference.frequentlyusedapps); } }
but don't know why, frequentlyusedapps
of userpreference
not injected expected. idea why?
update:
i think have figured out reason. it's because manually create userpreference
, use in provider. if remove provider userpreference
, , let dagger wire automatically, field frequentlyusedapps
injected. fault of not understanding dagger well.
i think need add objectgraph#inject calls.
in each class have @inject annotation, need call inject method of objectgraph created.
i have had been struggling while also. think basic pattern is:
- annotate fields indicate want inject them
- create module "provide" instances @injects
- create graph somewhere (seems people doing in application class)
- in classes want inject stuff module, instance of graph , call inject(this).
i started using singleton rather application class, because @ least have places want inject app itself.
so here doing, seems work pretty weill
public class injector { private static injector minjector; private objectgraph mobjectgraph; private myapp mapp; private injector() { } public static injector getinstance() { if (minjector == null) { minjector = new injector(); } return minjector; } protected list<object> getmodules() { return arrays.aslist( new applicationmodule(mapp), new androidmodule(mapp) ); } public void inject(object object) { getobjectgraph().inject(object); } public objectgraph getobjectgraph() { return mobjectgraph; } public void initialize(myapp app) { mapp = app; mobjectgraph = objectgraph.create(getmodules().toarray()); system.out.println(string.format("init object graph = %s",mobjectgraph.tostring())); } }
then in application class have constructor this:
public myapp() { system.out.println("myapp construtor"); injector.getinstance().initialize(this); injector.getinstance().inject(this); }
then when want inject this
@inject bus mbus; public gcmbroadcastreceiver() { injector.getinstance().inject(this); }
i have 2 modules , 1 production , 1 test
the production 1 has
@provides @singleton public bus providebus () { return busprovider.getinstance(); }
and test 1 has this
@provides @singleton public bus providebus () { return mock(bus.class); }
Comments
Post a Comment