My Guice is a little rusty (been 3 years) so bear with me. I have a custom API (#ContextSingleton) object that I need to #Inject into my various classes. This works fine when the target class extends from RoboActivity (or in my case, RoboSherlockActivity). However, when I want to inject it into a POJO, the injection fails and I get a null object.
Am I missing anything here? I tried writing a custom Provider for the API object (returning a new Api()), but the object creation graph isn't complete as any #Inject members within the API object is still null.
Right now I'm working around this by passing in the API object into POJOs instead of injecting it, but I'd like to eventually use #Inject for consistency.
I have this question, too. I think that we need to just use regular Guice for POJO cases. See my answer here: https://stackoverflow.com/a/24671352/189341
Related
I am great fan of Kotlin and how it allows us to write better code. One of the best features is interface implementation delegation which looks like this:
class A(val someObject:SomeInterface) : SomeInterface by someObject
someObject has to be singleton (object), has to be created using constructor after keyword by (but then you cannot reference to it, or maybe someone has idea how to do it?) or has to be provided in constructor.
In Android messy and bad world we are discouraged to use constructors in fragments and activites due to configuration changes. But how about this:
class MyFragment(val someObject:SomeInterface = SomeObjectImpl()):Fragment,SomeInterface by someObject
I tried to change configuration and event I allowed system to kill my appliction and still, everything is looking ok, my object is creating again and again with my fragment. Is this valid, or am I missing something?
Happy Kotlin everyone!
This is valid. The reason you're discouraged from overloading fragment constructors is that Android can recreate them, and it will use the default one: MyFragment()
But the way Kotlin implements default parameter values behind the scenes is by creating additional constructors. You can decompile your class and see it contains two constructors now, one receiving someObject, and another empty.
From the JVM perspective the empty constructor would look like this:
public A() {
this(new SomeObjectImpl());
}
Calling it will populate your fragment with new instances of implemented classes.
I started working in a project that already had Realm and the MVVM structure on it. As of now, all Realm methods are static and inside a RealmHelper class, except for some methods that are in the ViewModel classes of it's respective Activity. But RealmHelper class is starting to get bigger and bigger and kinda messy. I wanted to know what are your suggestions to rearrange my methods and classes when using Realm.
It's perfectly fine if you want to keep the RealmHelper class which manages all of the methods that your app can access. You may want to try to convert the methods to one liners that are being directed to another class internally.
So the structure might look something like this:
co.your.app.realmhelper
RealmHelper [public]
WriterHelper [Package Private]
ReaderHelper [Package Private]
So all of your logic is actually happening within the package private classes but the rest of your app would interface with the RealmHelper. The RealmHelper would just manage the instances of the package private classes and determine which methods should be invoked for those classes.
Your other option is to get rid of the RealmHelper in favor of smaller classes. Without knowing what your RealmHelper is actually doing it's difficult to give additional advice.
I came across the dagger library from Square and I'm currently making some tests. I'm new to the DI principle so be kind :)
So, I understand Dagger can inject fields and constructors. I'm also aware that in my activities, I have to .inject(this); so that injection can be done at runtime.
But what about an object O that needs to be created after the activity initialization ?
If O has injectable fields, I have to .inject(O); before using it otherwise I get a NullPointerException when accessing its injected variables. But if I write a injectable constructor, no problem, no runtime exception.
Of course I wrote my #Module according to the documentation.
Isn't it the purpose of Dagger to injects fields with no other code to write ? Do I have to manually .inject(); all my objects ? There is for sure a thing I'm missing.
Thanks in advance.
As you wrote Dagger supports two kind of injection:
field injection
constructor injection
In the first case you create an object then you inject the fields using inject method. For example in your onCreate of an Activity you will call this:
mObjectGraph.inject(this);
The second type of injection (constructor injection) requires that the object is created by Dagger. You simply mark the constructor with #Inject annotation then you can create instance like this:
HasInjectableConstructor instance = mObjectGraph.get(HasInjectableConstructor.class);
That's it. Maybe Dagger 2 will change something in this matter: squ.re/dagger2
I recently tried out AndroidAnnotations in Android. It has many interesting options and I like the way it reduces the boilerplate code.
However recently I came across the singleton scope for custom classes. I noticed that AndroidAnnotations does not restrict me from creating a new instance. For example CustomClassA obj = new CustomClassA();, even if the scope of CustomClassA is singleton.
As far as I know this should be restricted as per singleton pattern. I would like to have a solution to overcome this problem.
AndroidAnnotations never change original code.
So it's up to the developer to make the constructor protected (or friendly) on the original class. It can't be private because generated class extends of the original one (so it has to be visible for this one).
And the constructor is private on the generated class :)
I am getting into Inversion of Control, specifically using Guice and RoboGuice for Android and I have a question.
I have a method call that returns a Resource (which is essentially an XML or JSON String).
public Resource getResource(){
// Some implementation details that call a web service and throw the result in a string...
String resource = ........
}
The Resource class is really just a wrapped String, so I figured it made sense to pass it in in the constructor, since it is an essential part of a Resource object.
public class Resource{
Resource(String theXMLorJSON){
...
}
}
A couple of questions:
How do I construct a new Resource in the getResource call? I would think that I want to use IoC and not call new in the method.
If another class takes a Resource in the constructor, how can I use the Guice container to construct it when I need a dynamic String at construction time? I just asked a similar question and believe there may be a specific way to handle this using Guice.
Thanks so much!
I think you may be misunderstanding something about dependency injection. You don't need to try to avoid using new in all cases... you primarily want to avoid using new to create anything that you might want to be able to mock out for testing, and it's generally best to allow the container to wire up any class that depends on such an object.
Your Resource class, though, sounds like a simple value object that you can easily create manually in any testing you do. It also doesn't depend on any kind of services... it just contains a String. So there's no reason to try to have the container create it.
The class containing the getResource() method, on the other hand, you definitely want the container to create, because you'd like to be able to use something that depends on that class in testing without having to actually call a web service.
Note that if you have a class with a constructor that takes both dependencies you want injected by the container and parameters that are only known at runtime, you need to create an intermediate factory of some kind with a method that only takes the runtime parameters. With Guice you can automatically create such a factory from an interface using the Assisted Inject (not sure if that works with RoboGuice, but it's easy to create such a factory implementation manually too).