java - Dagger2: Injecting implementation classes provided by modules with component itself -
considering modules shared among one-another through dagger1 specification of complete=false, library=true
, can receive elements provided @provides
methods through constructor parameter, so.
public class getuserforusernametaskimpl implements getuserforusernametask { public static final string tag = getuserforusernametaskimpl.class.getsimplename(); private realm realm; private userrepository userrepository; public getuserforusernametaskimpl(realm realm, userrepository userrepository) { this.realm = realm; this.userrepository = userrepository; } @override public realmresults<userrlm> getusers() { try { realmresults<userrlm> users = userrepository.findall(realm); ... } @module(includes = {repositorymodule.class, realmmodule.class}) public class databasetaskmodule { @provides public getusersdatabasetask getusersdatabasetask(realm realm, userrepository userrepository) { return new getusersdatabasetaskimpl(realm, userrepository); } }
however, specify 1 dependency (the presenter
or customapplication
instance) holds component graph, , use component graph inject implementation classes.
public class getuserforusernametaskimpl implements getuserforusernametask { public static final string tag = getuserforusernametaskimpl.class.getsimplename(); @inject public realm realm; @inject public userrepository userrepository; protected presenter presenter; private boolean isinjected = false; public getuserforusernametaskimpl(presenter presenter) { this.presenter = presenter; } @override public realmresults<userrlm> getusers() { if(!isinjected) { presenter.getpresentercomponent().inject(this); isinjected = true; } try { realmresults<userrlm> users = userrepository.findall(realm); ... } } @module(includes = {presentermodule.class}) public class databasetaskmodule { @provides public getusersdatabasetask getusersdatabasetask(presenter presenter) { return new getusersdatabasetaskimpl(presenter); } }
and way, you'd have depend on presenter's object graph, , not have mess constructor parameters.
which 1 better approach?
edit: clearer , concrete example have in not-too-well refactored project following:
@module(includes = {contextmodule.class}) public class clientauthmodule { @provides public clientauthauthenticator clientauthauthenticator(customapplication customapplication) { return new clientauthauthenticator(customapplication); } }
then
public class customapplication extends application { public static class injectorinitializedevent { } public static class injectorinitializedeventproducer { @produce public injectorinitializedevent produceevent() { return new injectorinitializedevent(); } } private applicationcomponent applicationcomponent; @override public void oncreate() { super.oncreate(); applicationcomponent = injector.instance.initializeapplicationcomponent(); singletonbus.instance.getbus().post(new injectorinitializedevent()); singletonbus.instance.getbus().register(new injectorinitializedeventproducer()); //otto bus, event producer } public applicationcomponent getapplicationcomponent() { return this.applicationcomponent; } }
then
public class clientauthauthenticator { private customapplication customapplication; @inject public pemconverter pemconverter; @inject public keypaircreator keypaircreator; @inject public pkcs10csrcreator pkcs10csrcreator; @inject public keypairreader keypairreader; //... public clientauthauthenticator(customapplication customapplication) { this.customapplication = customapplication; singletonbus.instance.getbus().register(this); } @subscribe public void oninjectorinitializedevent(customapplication.injectorinitializedevent e) { customapplication.getapplicationcomponent().inject(this); singletonbus.instance.getbus().unregister(this); } ...
the question: way, dependencies provided application's component when injector ready, rather through constructor. approach? there caveats on long-run?
edit2: had injector here, pretty bad.
the 1 have in other project better constructed.
using constructor injection method annotating classes standard jsr-330 annotations, so:
the code decoupled concrete dependency injection library using. if need go to, let's say, old version of dagger, module , component definitions have change, not core classes.
your classes not need aware of details of how generated. tomorrow might have different components according scope, or might want component out of presenter classes. core classes should not change because of this.
it makes testing modules easier. no need run code generation or replace component instances through application. inject mock or test modules directly in constructor , done.
field , method injection should used in cases lifecycle of module out of control. case of activities or fragments in android environment. outside of use case, methods source of problems.
Comments
Post a Comment