I have the following code
public class AppGinModule extends AbstractGinModule{
#Override
protected void configure() {
bind(ContactListView.class).to(ContactListViewImpl.class);
bind(ContactDetailView.class).to(ContactDetailViewImpl.class);
}
}
#GinModules(AppGinModule.class)
public interface AppInjector extends Ginjector{
ContactDetailView getContactDetailView();
ContactListView getContactListView();
}
In my entry point
AppInjector appInjector = GWT.create(AppGinModule.class);
appInjector.getContactDetailsView();
Here ContactDetailView is always bind with ContactsDetailViewImpl. But i want that to bind with ContactDetailViewImplX under some conditions.
How can i do that? Pls help me.
You can't declaratively tell Gin to inject one implementation sometimes and another at other times. You can do it with a Provider or a #Provides method though.
Provider Example:
public class MyProvider implements Provider<MyThing> {
private final UserInfo userInfo;
private final ThingFactory thingFactory;
#Inject
public MyProvider(UserInfo userInfo, ThingFactory thingFactory) {
this.userInfo = userInfo;
this.thingFactory = thingFactory;
}
public MyThing get() {
//Return a different implementation for different users
return thingFactory.getThingFor(userInfo);
}
}
public class MyModule extends AbstractGinModule {
#Override
protected void configure() {
//other bindings here...
bind(MyThing.class).toProvider(MyProvider.class);
}
}
#Provides Example:
public class MyModule extends AbstractGinModule {
#Override
protected void configure() {
//other bindings here...
}
#Provides
MyThing getMyThing(UserInfo userInfo, ThingFactory thingFactory) {
//Return a different implementation for different users
return thingFactory.getThingFor(userInfo);
}
}
Related
I saw a method of using #inject annotation with parameter constructor. I found no use in #module in all parts of the project. I don't understand how this code injects or provides parameters in the constructor.
Can you help me analyze it?
Where is the datamanager provided?
In the whole project, #module + #provide is not used to provide datamanager. I only know that #inject can only annotate the parameterless constructor. I don't know where to instantiate the parameterless datamanager object. Thank you for your help
application:
public class Scallop extends Application {
private ApplicationComponent applicationComponent;
#Override
public void onCreate() {
super.onCreate();
applicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
}
public ApplicationComponent getApplicationComponent() {
return applicationComponent;
}
}
application module:
#Module
public class ApplicationModule {
private Scallop application;
public ApplicationModule(Scallop application) { // 提供类的构造器,传入Applicaton
this.application = application;
}
#Provides
#Singleton
Application provideApplication() {
return application;
}
#Provides
#ApplicationContext
Context provideContext() {
return application;
}
#Provides
#Singleton
Retrofit provideRetrofit() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return retrofit;
}
#Provides
#Singleton
GankIOService provideGankIOService(Retrofit retrofit) {
return retrofit.create(GankIOService.class);
}
}
#Singleton
#Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
Application getApplication();
DataManager getDataManager();
}
```
one class:
#Singleton
public class DataManager {
private GankIOService gankIOService;
private PreferencesHelper preferencesHelper;
#Inject
public DataManager(GankIOService gankIOService, PreferencesHelper preferencesHelper) {
this.gankIOService = gankIOService;
this.preferencesHelper = preferencesHelper;
}
}
fragment module:
#FragmentScope
#Component(modules = FragmentModule.class, dependencies = ApplicationComponent.class)
public interface FragmentComponent {
void inject(HomeFragment homeFragment);
void inject(GanHuoPageFragment pageFragment);
void inject(XianDuFragment xianDuFragment);
void inject(XianDuPageFragment xianDuPageFragment);
void inject(PicturesFragment picturesFragment);
void inject(MoreFragment moreFragment);
}
#FragmentScope
#Documented
#Scope
#Retention(value = RetentionPolicy.RUNTIME)
public #interface FragmentScope {
}
```
here Can't understand constructor with parameter is #inject
public class GanHuoPagePresenter extends BasePresenter<GanHuoPageContract.View>
implements GanHuoPageContract.Presenter {
private DataManager dataManager;
private Disposable disposable;
#Inject
public GanHuoPagePresenter(DataManager dataManager) { // here here
this.dataManager = dataManager;
}
#Override
public void detachView() {
super.detachView();
if (disposable != null) {
disposable.dispose();
}
}
#Override
public void getGanHuo(String category, final int page) {
final List<GanHuo> ganHuoList = new ArrayList<>();
Observable<BaseResponse<GanHuo>> observable = dataManager.getGanHuo(category, page);
disposable = observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.concatMap(new Function<BaseResponse<GanHuo>, ObservableSource<GanHuo>>() {
#Override
public ObservableSource<GanHuo> apply(#NonNull BaseResponse<GanHuo> ganHuoBaseResponse)
throws Exception {
return Observable.fromIterable(ganHuoBaseResponse.getResults());
}
}).filter(new Predicate<GanHuo>() {
#Override
public boolean test(#NonNull GanHuo ganHuo) throws Exception {
return !ganHuo.getType().equals("福利");
}
}).subscribe(new Consumer<GanHuo>() {
#Override
public void accept(GanHuo ganHuo) throws Exception {
ganHuoList.add(ganHuo);
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable throwable) throws Exception {
getView().showError(throwable.getMessage());
}
}, new Action() {
#Override`enter code here`
public void run() throws Exception {
getView().showList(ganHuoList, page);
}
});
}
}
This is how it is used in V in MVP mode:
#Inject GanHuoPagePresenter presenter
That's constructor injection. By marking a constructor with #Inject Dagger knows about the object and can create it when needed. There's no need for modules, e.g. the following is a valid Dagger setup to create some Foo.
public class Foo {
#Inject
public Foo() {}
}
#Component
interface MyComponent {
Foo getFoo();
}
That's not true that #Inject can only annotate the parameterless constructor. From documentation
Injectable constructors are annotated with #Inject and accept zero or more dependencies as arguments.
I found "your" project on Github so let's see where dependencies for GanHuoPagePresenter come from.
#Inject
public GanHuoPagePresenter(DataManager dataManager) {
this.dataManager = dataManager;
}
#Inject
public DataManager(GankIOService gankIOService,PreferencesHelper preferencesHelper){
// gankIOService is provided by ApplicationModule and preferencesHelper uses constructor injection
this.gankIOService = gankIOService;
this.preferencesHelper = preferencesHelper;
}
#Inject
public PreferencesHelper(#ApplicationContext Context context){
// context is provided again by ApplicationModule
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
}
How do I add a Subcomponent to a Module with an argument constructor?
Adding code here in addition to providing a github link:
ExampleApplication.java
public class ExampleApplication extends DaggerApplication {
#Inject
Database database;
#Override
public void onCreate() {
super.onCreate();
Timber.plant(new Timber.DebugTree());
Timber.i(database.name());
}
#Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerApplicationComponent
.builder()
.application(this)
.build();
}
}
ApplicationComponent.java
#ApplicationScope
#Component(modules = {
ApplicationModule.class,
AndroidSupportInjectionModule.class,
ActivityBindingModule.class,
DatabaseModule.class,
})
public interface ApplicationComponent extends AndroidInjector<ExampleApplication> {
Database database();
#Component.Builder
interface Builder {
#BindsInstance
Builder application(Application application);
ApplicationComponent build();
}
#Override
void inject(ExampleApplication instance);
}
DatabaseModule.java
#Module(subcomponents = DatabaseComponent.class)
public class DatabaseModule {
#Provides
#ApplicationScope
Database provideDatabase(
#NumberOfCores int numberOfCores,
DatabaseComponent.Builder databaseComponentBuilder) {
return databaseComponentBuilder
.databaseImplModule(new DatabaseImplModule(numberOfCores / 2))
.build()
.database();
}
}
DatabaseComponent.java
#Subcomponent(modules = DatabaseImplModule.class)
public interface DatabaseComponent {
// #PrivateToDatabase <- Is this a qualifier? A scope? Neither?
Database database();
#Subcomponent.Builder
interface Builder {
Builder databaseImplModule(DatabaseImplModule databaseImplModule);
DatabaseComponent build();
}
}
DatabaseImplModule.java
#Module
public class DatabaseImplModule {
DatabaseImplModule(int concurrencyLevel) {}
#Provides DatabaseConnectionPool provideDatabaseConnectionPool() {
return new DatabaseConnectionPool();
}
#Provides DatabaseSchema provideDatabaseSchema() {
return new DatabaseSchema();
}
}
Database.java
public class Database {
#Inject
public Database() { }
public String name() {
return "I have a name";
}
}
I tried to take a look at the dagger subcomponents documentation, specifically the section Subcomponents for encapsulation. I tried to create a code example
to see if I could make it work, but with no luck. Am I missing something in the documentation? (There is a line of code commented out the #PrivateToDatabase which I am not sure what kind of annotation it is).
I have a chain of Features. I would like to bind some beans inside ConfigFeature and then get them inside the MongoDBFeature. What methods should I use for that?
public final class IoCBinder extends AbstractBinder {
#Override
protected void configure() {
ConfigFeature.configureIoC(this);
MongoDBFeature.configureIoC(this);
}
}
Put some bean here:
public class ConfigFeature {
public static void configureIoC(AbstractBinder binder) {
// ....
binder.bind(configProvider).to(ConfigurationProvider.class).in(Singleton.class).named("configProvider");
}
}
And I would like to get configProvider bean here:
public class MongoDBFeature {
public static void configureIoC(AbstractBinder binder) {
// ?? get configProvider here ??
}
}
You can bind your bean to the ServiceLocator as shown in below example.
Service
public class TestService{
}
Binder
public static TestBinder extends AbstractBinder{
#Override
protected void configure() {
bind(new TestService()).to(TestService.class);
}
}
Feature 1
public class Feature1 implements Feature{
#Inject
private ServiceLocator locator;
#Override
public boolean configure(FeatureContext context) {
org.glassfish.hk2.utilities.ServiceLocatorUtilities.bind(locator,new TestBinder());
return true;
}
}
Note that a ServiceLocator instance is injected to Feature1 and the binder is bound to this locator instance.
Feature 2
public class Feature2 implements Feature{
#Inject
private TestService testService;
#Override
public boolean configure(FeatureContext context) {
return true;
}
}
Application/ResourceConfig class
public class TestConfig extends ResourceConfig {
register(Feature1.class);
// Need to make sure Feature1 is registered before Feature2.
// Another option is to register Feature2 in configure() method of Feature1 class.
register(Feature2.class);
}
I am currently dispatching my Business Logic via the Concurrency API JavaFX offers. But there is one part I stumble over which does not feel clean to me.
Basically if you create a Service which may look like this
public class FooCommand extends Service<Foo> {
#Override protected Task<Foo> createTask() {
return new Foo();
}
}
and I set the onSucceeded
FooCommand fooCommand = CommandProvider.get(FooCommand.class);
fooCommand.setOnSucceeded(new FooSucceededHandler());
fooCommand.start();
to an instance of this class
public class FooSucceededHandler implements EventHandler<WorkerStateEvent> {
#Override public void handle(WorkerStateEvent event) {
Foo f = (Foo) event.getSource().getValue();
}
}
But as you can see I need to cast the value of the Worker to (Foo). Is there some cleaner way to do it?
You could just make your own abstract class:
public abstract class EventCallback<T> implements EventHandler<WorkerStateEvent> {
#Override
public void handle(final WorkerStateEvent workerStateEvent) {
T returnType = (T) workerStateEvent.getSource().valueProperty().get();
this.handle(returnType);
}
public abstract void handle(T objectReturned);
}
And then using it:
final EventCallback<MonType> eventCallback = new EventCallback<MonType>() {
#Override
public void handle(final MonType objectReturned) {
// DO STUFF
}
};
As it is also an EventHandler, it is compatible with JavaFX concurrent API.
I have something like this:
request.findAllProjects().fire(new ExtReceiver<List<ProjectProxy>>() {
#Override
public void onSuccess(List<ProjectProxy> response) {
view.setProjects(response);
}
});
It is anonymous inner class of the abstract class ExtReceiver. The ExtReceiver is for handling the errors with an errorHandler which i want to provide.
public abstract class ExtReceiver<T> extends Receiver<T> {
private ErrorHandler errorHandler;
public ExtReceiver() {
}
#Inject
public void setErrorHandler(ErrorHandler errorHandler)
{
this.errorHandler = errorHandler;
}
#Override
public abstract void onSuccess(T response);
#Override
public void onFailure(ServerFailure error) {
errorHandler.exception(error);
}
#Override
public void onViolation(Set<Violation> errors) {
ValidationUtils.processViolation(errors);
}
}
I understand why this can't work, because i use the new Operator. But how could i do something like this. I want to have that anonymous class and not put it in an own file or something.
How could I inject that errorHandler? Thought about staticInjections, but it looked like this does not work too (Maybe because of the inheritance i create with doing an anonymous class)
In the opposite to normal Guice i don't know an injector.getInstance() call.
For information: That is a requestFactory call
Why don't you put the errorHandler parameter into the constructor of your abstract class instead creating a separate setErrorHandler setter, something like this:
public abstract class ExtReceiver<T> extends Receiver<T> {
private ErrorHandler errorHandler;
#Inject
public ExtReceiver(ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
}
Declare the bindings:
public class MyClientModule extends AbstractGinModule {
protected void configure() {
bind(ErrorHandler.class).in(Singleton.class);
}
}
Declare a Ginjector for your ErrorHandler class annotating it with the Module:
#GinModules(MyClientModule.class)
public interface MyErrorHandlerInjector extends Ginjector {
ErrorHandler getErrorHandler();
}
and then use it like this:
MyErrorHandlerGinjector injector = GWT.create(MyErrorHandlerGinjector.class);
ErrorHandler errorHandler = injector.getErrorHandler();
request.findAllProjects().fire(new ExtReceiver<List<ProjectProxy>>(errorHandler) {
#Override
public void onSuccess(List<ProjectProxy> response) {
view.setProjects(response);
}
});
I think this should work.