How to work with context singletons in Roboguice - android

I'm using #ContextSingleton to mark singletons that depend on the injection on contexts. From looking at RoboGuice sources and from my own tests it seems however as if it makes a difference between the Application context and different activity contexts. This makes perfectly sense, just that it is - at least for me - problematic when I'm using it together with the event management facility like this:
#ContextSingleton
public class Service {
#Inject
private Context context;
public void doSomething(#Observes MyEvent ev) {
...
}
}
Though the service is defined as singleton, no instance of it seems to be created until it is first injected somewhere, apparently through lazy-loading. So fireing a MyEvent does not make the listener call upon. We thought then we could "manually" eager-load the classes beforehand in our application like
RoboGuice.get(context).getInstance(Service.class);
and therefor get the listeners registered, but this only worked properly when executed within the Activity that later also injected the EventManager to fire the event, but not the application.
So, in an ideal world I'd expect that I could tell RoboGuice to which context it should bind a singleton, much like this
#ContextSingleton(MyApplication.class)
public class Service {
...
}
but apparently this is not possible.
What am I missing?

I think You're missing that events don't propogate across contexts and are context specific - see the "Things to be aware of" section in the (old, but still valid) events documentation. So even if your singleton is loaded in the application context, it can't be made aware of events occurring within the context of each activity. I assume they had a good reason for doing it that way, but Maybe if you subclass Application you can inject an EventManager there to be globally accessible.
I haven't tried it so I'm not sure it will work, and at any rate at that point you'd have to be injecting events into a different EventManager, so you might be better off defining an interface for this singleton and work with it that way, since events won't propogate the way you'd like them to.

#JRaymond is right. An instance of a RoboGuice Event listener can't listen to events in more than one context.
But this can be easily solved. Don't make your singleton listen to events directly. Each activity can listen to its own events and then put the singletong in a given state :
public class MyActivity extends RoboActivity {
#Inject
private InsideAppManager mInsideAppManager;
public void onHandleResumeEvent( #Observes OnResumeEvent onStartEvent ) {
mInsideAppManager.setInsideApp(true);
}
public void onHandlePauseEvent( #Observes OnPauseEvent onStopEvent ) {
mInsideAppManager.setInsideApp(false);
}
}
And your singleton :
#Singleton
public class InsideAppManager {
private boolean isInsideApp;
public boolean isInsideApp() {
return isInsideApp;
}
public void setInsideApp(boolean isInsideApp) {
this.isInsideApp = isInsideApp;
}
}

Related

Difference between using an Interface and directly passing Activity to implement Callback

I have noticed that I can create a callback by using two methods:
Receive an interface at the constructor of the class implementing the callback.
Receive the activity itself at the constructor of the class implementing the callback.
First Approach
For example I could do this:
public MyClass(MyInterface listener) {
this.listener = listener;
}
And I could call myCallBackFunction() defined in MyActivity (which implements MyInterface) by writing listener.myCallBackFunction()
Second Approach
Or I could do this:
public MyClass(MyActivity activity) {
this.activity = activity;
}
And I could call myCallBackFunction() defined in MyActivity by writing activity.myCallBackFunction()
My concern: Is one approach better than the other? And if so, why?
Usually speaking, you'd better use first approach. The reason is here:
Suppose you have 4 classes, first is Vehicle, second is Bicycle, third is Bus and third is Subway. Bicycle, Bus and Subway are subclasses of Vehicle. There may be a method call drive(), which should have a parameter. Which one do you think best for parameter type? Bicycle, Bus, Subway, or Vehicle?
Apparently, passing Vehicle is best because you may want to add other kinds of vehicles in the future or you don't want to write nearly same code for different kinds of vehicles in your project. It is same to use Interface rather than specific class.
As a result, passing an interface to a method is always correct and better than passing a specific type of object to it. You can always implement the interface in other classes and they will also be parameter of that method. You don't need to think about actual type of the parameter, which will confuse you and make you think more about specific code for specific type. Instead, only one type, one piece of code macroscopically.
So the conclusion is: using MyActivity is good, but using MyInterface is better.
I think it can depend on what you're trying to achieve: the first approach may in general be better suited since MyClass is not required to know anything about the implementation of that interface method, so it's great for passing different objects (e.g. a RecyclerView Adapter being created with an OnItemClickedListener injected in the constructor can be re-used in different activities/fragments implementing the interface, whilst the adapter doesn't need to change). It helps to prevent coupling.
The second approach leaves one wondering: is MyClass tied to the activity lifecycle? It may still hold a reference to the activity after that activity has actually been destroyed by the system, which would leak memory as the Activity object is not garbage-collected. It's a matter of design, and can be seen as code smell, can you not achieve what you wanted within the activity itself, and rely on the lifecycle callbacks onCreate/.../onDestroy?
Is one approach better than the other? And if so, why?
Using Interface is the best way..
Assume that you are having
1) Activity MyActivity
2) class which extends Activity or View or Asynctask is Myclass.
Both MyActivity and Myclass are Implements MyInterface
If you are passing Activity you need to add one more constructor
public MyClass(MyActivity activity) {
this.activity = activity;
}
public MyClass(Myclass myclass) {
this.myclass= myclass;
}
If you are using interface
public MyClass(MyInterface listener) {
this.listener = listener;
}
that's it.
In one approach you are creating an instance of Interface and in another an instance of implementing activity. what is best is:
Interface interface;
public myClass(Activity acitivity)
{
interface = (Interface)activity;
}
i.e. typecast activity to interface. Now you can callback the overridden functions in Activity.
This way you can now loose information of Activity's functions and just access the overriden functions of interface from the activity.
You can avoid typecasting and create an object of Activity, if you need access to interface callbacks AND the activity's function/variables.
It depends on your needs.

Which context is injected by roboguice?

I'd like to know which context Roboguice injects, is it the application context or the current activity?
I'm trying to use both Roboguice and Robospice. I'm injecting Robospice's SpiceManager in a fragment but the fragment doesn't know about the SpiceManager, it sees it through an interface, let's say MyInterface.
public class MyFragment extends RoboFragment {
//this is where the SpiceManager gets injected
#Inject MyInterface manager;
...
}
//this is the implementation that I'm going to inject
//it is simultaneously an event listener for the fragment's life cycle events so that the
//SpiceManager can be appropriately started and stopped.
public class MyManager implements MyInterface {
private SpiceManager spiceManager = new SpiceManager(MySpiceService.class);
//Which context will get injected here? How can I make Roboguice inject a specific context that I want, for example, a specific activity that I want.
private #Inject Context context;
//Here, I need to start the SpiceManager
public void myFragmentOnStart(#Observes OnStartEvent onStart) {
//SpiceManager requires a context, more specifically an activity which will be destroyed and then garbage collected, so It shouldn't be an application context because the resources SpiceManager uses will never be released.
spiceManager.start(context);
}
public void myFragmentOnStop(#Observes OnStopEvent onStop){
if (spiceManager.isStarted()) {
spiceManager.shouldStop();
}
}
}
My questions are:
Can RoboGuice observe fragment events beside Activity events, the documentation isn't clear?
Am I right in thinking that SpiceManager needs a context that will be destroyed when the fragment/activity is destroyed? I've had a look at the code of SpiceManager.start(Context context) and it creates a WeakReference to the passed Context.
How can I make RoboGuice inject a specific Context/Activity?
Is it possible to do so without MyFragment knowing that the MyInterface object it uses needs a Context?
By the way I found out that OnStopEvent has a getActivity() method, so there's no problem getting the Activity in onStop, but OnStartEvent is just an empty class.
So many questions ;)
A) Can RoboGuice observe fragment events beside Activity events, the documentation isn't clear ?
Event can be anything in RG. By default RG offers some nice events to be notified of lifecycle of an activity. Release 3.1 of RG is actually adding some new events for Fragments. This should be released in a couple of weeks.
But what you do on the event side is perfectly legitimate. Just to be clear. You are listening to the activity lifecycle from within a fragment. Why not ?
The only thing you need is to register to this instance of event manager of the activity. Add #Inject EventManager eventManager to your fragment. This is enough for RG to register your listener automatically.
B) RS will need a context only for callbacks, not to execute a request. The request is gonna be executed in a service. The context you pass to RS is just used to say "If this context dies, then all listeners will die, don't notify them. But still, go ahead, execute the request and cache the result."
Here it's a bit complex the way you do it. The easiest is really to manage a spice manager at the activity level. Send events from your fragments to your activity to ask it to launch requests when needed. That the easiest.
But it's also possible to have spicemanager managed at the fragment level. In that case, manage your spicemanager lifecycle in the fragment itself with its onStart/onStop methods.
C) Is it possible to do so without MyFragment knowing that the MyInterface object it uses needs a Context?
I didn't get it.

Why extend the Android Application class?

An extended Application class can declare global variables. Are there other reasons?
Introduction:
If we consider an apk file in our mobile, it is comprised of
multiple useful blocks such as, Activitys, Services and
others.
These components do not communicate with each other regularly and
not forget they have their own life cycle. which indicate that
they may be active at one time and inactive the other moment.
Requirements:
Sometimes we may require a scenario where we need to access a
variable and its states across the entire Application regardless of
the Activity the user is using,
An example is that a user might need to access a variable that holds his
personnel information (e.g. name) that has to be accessed across the
Application,
We can use SQLite but creating a Cursor and closing it again and
again is not good on performance,
We could use Intents to pass the data but it's clumsy and activity
itself may not exist at a certain scenario depending on the memory-availability.
Uses of Application Class:
Access to variables across the Application,
You can use the Application to start certain things like analytics
etc. since the application class is started before Activitys or
Servicess are being run,
There is an overridden method called onConfigurationChanged() that is
triggered when the application configuration is changed (horizontal
to vertical & vice-versa),
There is also an event called onLowMemory() that is triggered when
the Android device is low on memory.
Application class is the object that has the full lifecycle of your application. It is your highest layer as an application. example possible usages:
You can add what you need when the application is started by overriding onCreate in the Application class.
store global variables that jump from Activity to Activity. Like Asynctask.
etc
Sometimes you want to store data, like global variables which need to be accessed from multiple Activities - sometimes everywhere within the application. In this case, the Application object will help you.
For example, if you want to get the basic authentication data for each http request, you can implement the methods for authentication data in the application object.
After this,you can get the username and password in any of the activities like this:
MyApplication mApplication = (MyApplication)getApplicationContext();
String username = mApplication.getUsername();
String password = mApplication.getPassword();
And finally, do remember to use the Application object as a singleton object:
public class MyApplication extends Application {
private static MyApplication singleton;
public MyApplication getInstance(){
return singleton;
}
#Override
public void onCreate() {
super.onCreate();
singleton = this;
}
}
For more information, please Click Application Class
Offhand, I can't think of a real scenario in which extending Application is either preferable to another approach or necessary to accomplish something. If you have an expensive, frequently used object you can initialize it in an IntentService when you detect that the object isn't currently present. Application itself runs on the UI thread, while IntentService runs on its own thread.
I prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences. There are also ways to pass data from a Fragment to its parent Activity using interfaces.
The Application class is a singleton that you can access from any activity or anywhere else you have a Context object.
You also get a little bit of lifecycle.
You could use the Application's onCreate method to instantiate expensive, but frequently used objects like an analytics helper. Then you can access and use those objects everywhere.
Best use of application class.
Example: Suppose you need to restart your alarm manager on boot completed.
public class BaseJuiceApplication extends Application implements BootListener {
public static BaseJuiceApplication instance = null;
public static Context getInstance() {
if (null == instance) {
instance = new BaseJuiceApplication();
}
return instance;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onBootCompleted(Context context, Intent intent) {
new PushService().scheduleService(getInstance());
//startToNotify(context);
}
Not an answer but an observation: keep in mind that the data in the extended application object should not be tied to an instance of an activity, as it is possible that you have two instances of the same activity running at the same time (one in the foreground and one not being visible).
For example, you start your activity normally through the launcher, then "minimize" it. You then start another app (ie Tasker) which starts another instance of your activitiy, for example in order to create a shortcut, because your app supports android.intent.action.CREATE_SHORTCUT. If the shortcut is then created and this shortcut-creating invocation of the activity modified the data the application object, then the activity running in the background will start to use this modified application object once it is brought back to the foreground.
I see that this question is missing an answer. I extend Application because I use Bill Pugh Singleton implementation (see reference) and some of my singletons need context. The Application class looks like this:
public class MyApplication extends Application {
private static final String TAG = MyApplication.class.getSimpleName();
private static MyApplication sInstance;
#Contract(pure = true)
#Nullable
public static Context getAppContext() {
return sInstance;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() called");
sInstance = this;
}
}
And the singletons look like this:
public class DataManager {
private static final String TAG = DataManager.class.getSimpleName();
#Contract(pure = true)
public static DataManager getInstance() {
return InstanceHolder.INSTANCE;
}
private DataManager() {
doStuffRequiringContext(MyApplication.getAppContext());
}
private static final class InstanceHolder {
#SuppressLint("StaticFieldLeak")
private static final DataManager INSTANCE = new DataManager();
}
}
This way I don't need to have a context every time I'm using a singleton and get lazy synchronized initialization with minimal amount of code.
Tip: updating Android Studio singleton template saves a lot of time.
I think you can use the Application class for many things, but they are all tied to your need to do some stuff BEFORE any of your Activities or Services are started.
For instance, in my application I use custom fonts. Instead of calling
Typeface.createFromAsset()
from every Activity to get references for my fonts from the Assets folder (this is bad because it will result in memory leak as you are keeping a reference to assets every time you call that method), I do this from the onCreate() method in my Application class:
private App appInstance;
Typeface quickSandRegular;
...
public void onCreate() {
super.onCreate();
appInstance = this;
quicksandRegular = Typeface.createFromAsset(getApplicationContext().getAssets(),
"fonts/Quicksand-Regular.otf");
...
}
Now, I also have a method defined like this:
public static App getAppInstance() {
return appInstance;
}
and this:
public Typeface getQuickSandRegular() {
return quicksandRegular;
}
So, from anywhere in my application, all I have to do is:
App.getAppInstance().getQuickSandRegular()
Another use for the Application class for me is to check if the device is connected to the Internet BEFORE activities and services that require a connection actually start and take necessary action.
Source: https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class
In many apps, there's no need to work with an application class directly. However, there are a few acceptable uses of a custom application class:
Specialized tasks that need to run before the creation of your first activity
Global initialization that needs to be shared across all components (crash reporting, persistence)
Static methods for easy access to static immutable data such as a shared network client object
You should never store mutable instance data inside the Application object because if you assume that your data will stay there, your application will inevitably crash at some point with a NullPointerException. The application object is not guaranteed to stay in memory forever, it will get killed. Contrary to popular belief, the app won’t be restarted from scratch. Android will create a new Application object and start the activity where the user was before to give the illusion that the application was never killed in the first place.
To add onto the other answers that state that you might wish store variables in the application scope, for any long-running threads or other objects that need binding to your application where you are NOT using an activity (application is not an activity).. such as not being able to request a binded service.. then binding to the application instance is preferred. The only obvious warning with this approach is that the objects live for as long as the application is alive, so more implicit control over memory is required else you'll encounter memory-related problems like leaks.
Something else you may find useful is that in the order of operations, the application starts first before any activities. In this timeframe, you can prepare any necessary housekeeping that would occur before your first activity if you so desired.
2018-10-19 11:31:55.246 8643-8643/: application created
2018-10-19 11:31:55.630 8643-8643/: activity created
You can access variables to any class without creating objects, if its extended by Application. They can be called globally and their state is maintained till application is not killed.
The use of extending application just make your application sure for any kind of operation that you want throughout your application running period. Now it may be any kind of variables and suppose if you want to fetch some data from server then you can put your asynctask in application so it will fetch each time and continuously, so that you will get a updated data automatically.. Use this link for more knowledge....
http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android

Dagger & Android - race conditions in tests?

I am using Dagger to inject dependencies into activities in an Android project. All of the providers are kept in one module which is stored and managed by the Application subclass. Activities inject their dependencies in onCreate(), getting the module from the context.
In tests, I sometimes need to swap the default module for another one. I am using ActivityAndroidTestCase2. I get the application context before I call getActivity(), then substitute the module, like this:
Context applicationContext = getInstrumentation()
.getTargetContext().getApplicationContext();
module.setAppContext(applicationContext);
Thread.sleep(1000); // note this
((ObjectGraphProvider) applicationContext).setModule(module);
The MyApplication code:
public class MyApp extends Application implements ObjectGraphProvider {
private ObjectGraph objectGraph;
private Object module;
public MyApp() {
super();
ApplicationContextModule myModule = new DefaultModule();
myModule.setAppContext(this);
this.module = myModule;
}
#Override
public void onCreate() {
super.onCreate();
objectGraph = ObjectGraph.create(module);
}
#Override
public ObjectGraph objectGraph() {
return objectGraph;
}
/* Test only */
public void setModule(Object module) {
this.module = module;
objectGraph = ObjectGraph.create(module);
}
}
Sadly, the test fails from time to time - that's the reason for the sleep() in the first code snippet. The longer the thread sleeps, the smaller the chance of the failure, but it does not solve the problem for good.
Any ideas about what causes this strange behaviour and how to get over this issue?
I've encountered similar problems in my tests using Dagger and Cucumber-jvm. Here are a few gotchas to look out for:
When you set your object graph to a new one, make sure there are no lingering references to components in the old graph. This means any Activities, Services, BroadcastReceivers, etc., that may still be active in the system and holding references to objects injected by your graph. Consider finishing all open activities before resetting the graph. In my case, I had a background service that was sticking around with injected references from the old graph. I had to explicitly call stopSelf() in the service to keep it from sticking around between test runs. This allowed it to get injections from the new graph when it started again.
Use completely random IDs for PendingIntents, Notifications, and any other parts Android that take IDs. I was accidentally re-using IDs in my PendingIntents and this caused some tricky errors.
Look for any other state that could persist before and after you reset the graph. I eventually came up with a procedure to completely clear my app state and start fresh: Clear all shared preferences, cancel all notifications, finish all opened activities, and then reset the graph.

Different Instance of Applicationcontext in Broadcastreceiver

I want to access a "global" variable in my MyApp(extends Application) from a broadcastreceiver (registered in the manifest) and e.g. multiple activities. Now I seem to have different instances of my MyApp: one for the BCR and one for the activities. Could sb help me with my problem?
thanks alot
Joerg
What I get from this is that you are trying to create a method to having a single Context object. First off, to do this you would need a Singleton Pattern of MyApp to create your "global" variable. However I would advice against this for these reasons:
Different application components by default have different contexts (base, application).
A BroadcastReceiver defined in the manifest is invoked by the OS, not by your application.
Using a Singleton Pattern for a context object will lead to some very nasty dependencies.
You are going against the design and beauty of the Android Framework.
I would suspect the reason you are doing this is so your MyApp class can start different activities. This makes sense, but... you can get a Context Object from almost anywhere. Many things in Android extend the ContextWrapper class (think Java Objects with the Object class). So there is really no reason to ever have a "global" instance of this. In fact your BroadcastReceiver's onReceive() method accepts a context parameter. You can use this to start activities and what not.
If this is not why you are wanting the MyApp singleton class - and there are justifiable reasons for needing it, I would look at the implementation designed by Bill Pugh as it is the safest in Java taking into account thread synchronization and locking.
Hope this helps. Remember, don't fight the SDK, let it work for you!
I had a similar problem, I was able to access an object in the activity using this pattern:
public class MyReceiver extends android.content.BroadcastReceiver {
private Object _object;
public MyReceiver(Someobject) {
_object = the object;
}
#Override
public void onReceive(Context context, Intent intent) {
Do something to the object.
}
}
Then call MyReceiver(theobject) instead of new BroadcastReceiver().

Categories

Resources