I am using ionic 2 with storage.
If I keep the storage code outside of a function it does not work.
kindly let me know.
constructor(public navCtrl: NavController,
public settings: Settings,
public formBuilder: FormBuilder,
public navParams: NavParams,
public translate: TranslateService,
private storage : Storage) {
}
this.settings.load().then(() => {
this.settingsReady = true;
this.options = this.settings.allSettings;
this._buildForm();
});
this.storage.set('nam','par');
}
The constructor is a special function of the class that is responsible for initializing the variables of the class. TypeScript defines a constructor using the constructor keyword. A constructor is a function and hence can be parameterized. Up until the variable get's initialized it remains undefined. so, you can't do in that way and also make no sense, constructor is initialized before anything so either you can do the same operation within constructor or use any life cycle event in ionic to do so.
Related
I am pretty new to Dagger and finding the component body a bit difficult to understand,having 2 specific questions related to the component implementation:
1)
#Singleton
#Component(modules = { UserModule.class, BackEndServiceModule.class })
public interface MyComponent {
BackendService provideBackendService();// Line 1
void inject(Main main); // Line 2
}
What is the purpose of Line 2? also will an instance of backendService be created even if line 1 is removed?
and also in the below code where the implementation of the above interface is generated , what does the component.inject(this) actually do?
public class Main {
#Inject
BackendService backendService; //
private MyComponent component;
private Main() {
component = DaggerMyComponent.builder().build();
component.inject(this);
}
private void callServer() {
boolean callServer = backendService.callServer();
if (callServer) {
System.out.println("Server call was successful. ");
} else {
System.out.println("Server call failed. ");
}
}
and also why has the backendservice not obtained using component.provideBackendService()
What is the purpose of void inject(Main main);?
It lets you perform field injection on concrete class Main, assuming that Main is a class that cannot be created by Dagger
where the implementation of the above interface is generated , what does the component.inject(this) actually do?
It uses MemberInjectors to inject the package-protected or public fields marked with #Inject. You can see the implementation of inject(Main) method in DaggerMyComponent class.
Of course, if possible it is better to make it so that:
1.) Main does not instantiate/know about its own injector
2.) Main is created by the Dagger component and #Inject constructor is used
#Singleton
public class Main {
private final BackendService backendService;
#Inject
Main(BackendService backendService) {
this.backendService = backendService;
}
}
I have a component (ItemDetailsPage) that is importing a helper service
import { Helper } from './../../app/Helper';
and in the constructor I have
constructor(public viewCtrl: ViewController, public navCtrl: NavController, public navParams: NavParams,
public helper: Helper...)
In Helper.ts I have the following:
import { ItemDetailsPage } from './../pages/item-details/item-details';
and I use it like that:
showItemWindow() {
let itemModal = this.modalCtrl.create(ItemDetailsPage, null, { cssClass: "modal-fullscreen" });
itemModal.present();
}
When doing the above, I get "cannot resolve all parameters for ItemDetailsPage... I understand that it's because of a circular dependency. I can move showItemWindow to another component and it works but the reason I put it in the helper, is because I need it from 3 different pages and I wanted one place to open this window.
Is there another cleaner solution for this or moving it to 3 different component is the right one? Thanks
Notice how you have 3 periods ... after your declaration of the Helper class in the constructor.Your constructor method should look like below.
constructor(public viewCtrl: ViewController, public navCtrl: NavController, public navParams: NavParams,
public helper: Helper)
I want to be able to simply specify what is needed without adding strings or symbols. This seems to work for declaring the binding:
container.bind<Weapon>(Shuriken);
But I get a run-time error if I don't use #inject and don't know what to put in it when it's being injected:
public constructor(
#inject() weapon: Weapon // compile-time error
) {
When you use an interface (I assume that Weapon is an interface) you need to ensure that the same ID is used when you declare the binding:
container.bind<Weapon>(Shuriken).toSelf();
And then you declare the injection:
#injectable()
class SomeClass {
public constructor(
#inject(Shuriken) weapon: Weapon; // Use the right ID!
) {
However, using the class removes the benefits of dependency injection. If you want you to use classes you could actually do something more simple:
#injectable()
class SomeClass {
public constructor(
weapon: Shuriken; // Use the class as Type!
) {
The recommended solution is to use strings or symbols as IDs:
const TYPE = { Weapon: "Weapon" };
container.bind<Weapon>(TYPE.Weapon).to(Shuriken);
#injectable()
class SomeClass {
public constructor(
#inject(TYPE.Weapon) weapon: Weapon;
) {
I'm creating a simple page and I need to NavController and AlertController, as far as I understood constructor should look like this:
constructor(public alertCtrl: AlertController
, navCtrl: NavController) { }
my problem is that navController is not recognised later in the code. If I change the line to
constructor(public navCtrl: NavController,
alertCtrl: AlertController) { }
Then alertController stops working. Im pretty sure its some newbie syntax issue.
You need to specify public or private for both of them individually
constructor(public navCtrl: NavController,
public alertCtrl: AlertController) { }
You need to add private or public to the services you want to inject because these are parameter proberties. Adding a modifier allows you to create and initialize a member in the same place.
So your code should look like this:
constructor(
public navCtrl: NavController,
public alertCtrl: AlertController
) {}
or this:
constructor(
private navCtrl: NavController,
private alertCtrl: AlertController
) {}
Parameter properties are declared by prefixing a constructor parameter with an accessibility modifier or readonly, or both. Using private for a parameter property declares and initializes a private member; likewise, the same is done for public, protected, and readonly.
I have set up dagger2 dependencies in my app as I understand it and through the many examples. What I have not found is the proper way to use all of the dependencies once they are injected.
Each of the singletons in the module depends on the output of the singleton before it. How is the entire dependency graph used without calling each singleton in turn to get the required inputs?
Given the following:
AppComponent
#Singleton
#Component(modules = {
DownloaderModule.class
})
public interface AppComponent {
void inject(MyGameActivity activity);
}
DownloaderModule
#Module
public class DownloaderModule {
public static final String NETWORK_CACHE = "game_cache";
private static final int GLOBAL_TIMEOUT = 30; // seconds
public DownloaderModule(#NonNull String endpoint) {
this(HttpUrl.parse(endpoint));
}
#Provides #NonNull #Singleton
public HttpUrl getEndpoint() {
return this.endpoint;
}
#Provides #NonNull #Singleton #Named(NETWORK_CACHE)
public File getCacheDirectory(#NonNull Context context) {
return context.getDir(NETWORK_CACHE, Context.MODE_PRIVATE);
}
#Provides #NonNull #Singleton
public Cache getNetworkCache(#NonNull #Named(NETWORK_CACHE) File cacheDir) {
int cacheSize = 20 * 1024 * 1024; // 20 MiB
return new Cache(cacheDir, cacheSize);
}
#Provides #NonNull #Singleton
public OkHttpClient getHttpClient(#NonNull Cache cache) {
return new OkHttpClient.Builder()
.cache(cache)
.connectTimeout(GLOBAL_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(GLOBAL_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(GLOBAL_TIMEOUT, TimeUnit.SECONDS)
.build();
}
MyGameApp
public class MyGameApp extends Application {
private AppComponent component;
private static Context context;
public static MyGameApp get(#NonNull Context context) {
return (MyGameApp) context.getApplicationContext();
}
#Override
public void onCreate() {
super.onCreate();
component = buildComponent();
MyGameApp.context = getApplicationContext();
}
public AppComponent component() {
return component;
}
protected AppComponent buildComponent() {
return DaggerAppComponent.builder()
.downloaderModule(new DownloaderModule("https://bogus.com/"))
.build();
}
}
I'll try to shed some light into this, but there are several ways you can read this. I prefer a bottom up approach - Basically start on what your objects require and work my way up. In this case, I would start at MyGameActivity. Unfortunately, you didn't paste the code for this, so I'll have to be a bit creative, but that's ok for the purpose of the exercise.
So in your app you're probably getting the AppComponent and calling inject for your MyGameActivity. So I guess this activity has some injectable fields. I'm not sure if you're using there directly OkHttpClient but let's say you do. Something like:
public class MyGameActivity extends SomeActivity {
#Inject
OkHttpClient okHttpClient;
// ...
}
The way I like to think about this is as follows. Dagger knows you need an OkHttpClient given by the AppComponent. So it will look into how this can be provided - Can it build the object itself because you annotated the constructor with #Inject? Does it require more dependencies?.
In this case it will look into the modules of the component where this client is being provided. It will reach getHttpClient and realise it needs a Cache object. It will again look for how this object can be provided - Constructor injection, another provider method?.
It's again provided in the module, so it will reach getNetworkCache and once more realise it needs yet another dependency.
This behaviour will carry on, until it reaches objects that require no other dependencies, such as your HttpUrl in getEndpoint.
After all this is done, your OkHttpClient can be created.
I think it's easy to understand from this why you can't have cycles in your dependency graph - You cannot create an object A if it depends on B and B depends on A. So imagine that for some weird reason you'd reach the method getEndpoint which would depend on the OkHttpClient from that module. This wouldn't work. You'd be going in circles an never reach an end.
So if I understand your question: How is the entire dependency graph used without calling each singleton in turn to get the required inputs?
It's not. It has to call all the methods to be able to get the singletons. At least the first time they're provided within the same component/scope. After that, as long as you keep the same instance of your component, the scoped dependencies will always return the same instance. Dagger will make sure of this. If you'd for some reason destroy the component or recreate it, then the dependencies wouldn't be the same instances. More info here. In fact this is true for all scopes. Not just #Singletons.
However, as far as I can tell you're doing it right. When your application is created you create the component and cache it. After that, every time you use the method component() you return always the same component and the scoped dependencies are always the same.