Dagger & Android - race conditions in tests? - android

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.

Related

dagger2 activityscope providing same object of injected dependencies with different activities

Following code creates & shares same object of injected dependencies(ViewsApiEnd ) with different activities rather than creating different per activity.
#ActivityScope
#Component(dependencies = HttpComponent.class, modules = ViewsApiModule.class)
public interface ViewsApiComponent {
void inject(MainActivity activity);
void inject(SecondActivity activity2);
}
module:
#Module
public class ViewsApiModule {
#Provides
#ActivityScope
public ViewsApiEnd providesGitHubInterface(Retrofit retrofit) {
return retrofit.create(ViewsApiEnd.class);
}
}
Scope:
#Scope
#Retention(RetentionPolicy.RUNTIME)
public #interface ActivityScope{
}
Full Source: Github(If anyone could fork & correct scope issue it'll be helpful. Also checke void logInstances() for verifying object creation )
How should I declare ViewsApiComponent if I want dagger2 to create different objects of injected deps( ViewsApiEnd) for different activities(MainActivity , SecondActivity )?
I'm assuming by different object you mean different instances and not different implementations.
The key to this is scopes and how you manage your components. In particular ViewsApiComponent.
Let's start with scopes. A scope in dagger is nothing but an annotation that tells dagger that during the life of a given component, as long as an object annotated with a given scope is required, the instance provided will always be the same. In other words, within the same component scoped dependencies will be singleton.
In your code, this ActivityScope is the scope tied to ViewsApiEnd. Now what people usually don't get about scopes is the first part of - "... as long as the component is alive scoped dependencies are singleton". Basically this says, if your component's instance remains the same, then all your scoped instances will be the same.
In your code this is the case because you pin mViewsApiComponent to the application class and you never recreate it. So in your activities when you do this:
// ...
((MyApp) getApplication()).getGitHubComponent().inject(this);
// ...
You're always using the same component, hence same scopes, hence same instance of ViewsApiEnd.
You need to make sure the scoped dependencies have a proper scoped handling. If you want a dependency that is different per activity, then you want to manage the component that takes care of this dependency on a per activity basis.
There's different ways of doing this. I think the simplest one in your case is to move the creation of ViewsApiComponent to your activities. Make sure you nullify the component in onDestroy. Something like this:
private ViewsApiComponent mViewsApiComponent;
#Override
public void onCreate() {
super.onCreate();
getComponent().inject(this);
}
#Overrides
public void onDestroy() {
super.onDestroy();
mViewsApiComponent = null;
}
private ViewsApiComponent getComponent() {
if (mViewsApiComponent == null) {
mViewsApiComponent = DaggerViewsApiComponent.builder()
.httpComponent(((MyApp) getApplication()).getNetComponent())
.build();
}
return mViewsApiComponent;
}
You can even put this code in a base activity and inherit from it in each activity.
Important thing to notice is that the component is now managed by the activity, or better put it's tied to its life-cycle. This ensures the component lives during the life time of the activity and all scoped dependencies are the same within that activity. For another activity a new component will be created and the new object instances will be used, but within the activity they will remain the same.
Now I've explained all of this just for the sake of trying to help you out with components and scopes, but truth is that what you're currently providing in the component's modules are all objects that should indeed be singleton throughout the app's life. So in fact, the way you have it now is the most correct approach at least in my opinion.
Hope this helps

Dagger 2: Scoping and handling release/cleanup of provided injection

Is it possible to scope this and provide a release method in the module or elsewhere to prevent memory leaks. Ex. I need to close a database connection in onDestroy() but it would be nice if this could be handled by the module itself.
Consider the following example* code.
*Read the error prone code at your own risk
Module
#dagger.Module
#lombok.NoArgsConstructor
public class PersistenceModule {
#Provides
#Singleton
DatabaseProvider providesDatabaseHelper(Context context) {
return new DatabaseProvider(context);
}
}
Activity
public class SomeActivity extends Activity{
#javax.inject.Inject DatabaseProvider provider;
//..onCreate omitted where injection happens.
#Override
protected void onDestroy() {
//Close database and cleanup.
provider.release();
provider = null;
super.onDestroy();
}
}
Your sample seems error-prone, as you are scoping your DatabaseProvider with a #Singleton scope, but use and clean it up in an activity.
A Module just helps creating objects—especially if there is no injectable constructor or it needs further initialization—and is not aware of further lifecycle events. It supplies its objects to a Component, which just holds and creates the object graph needed to inject your classes. In the end both are just plain old java objects and a scope on a component is nothing more than syntactic sugar helping with compile time validation.
In any case, you should handle your cleanup at the same scope that you provide your dependency. #Singleton scope should therefore be cleaned up in the application object that is also holding the application component. If you clean up a singleton scoped object in an activity, the next activity accessing it would be accessing an object in a closed state.
If every activity should have its own accessor and clean it up after being used, then you should switch to some activity based scope. Additional scopes are just annotations that you can create yourself.
The actual cleanup
All this said, I would not include "clean up" logic in my modules, because most people would not expect to find it there.
#Module
Annotates a class that contributes to the object graph.
Dagger is a dependency injection framework that provides dependencies for easier usage of interfaces and looser coupling of your classes. It is to reduce boiler plate code of object creation and what you do with the actual objects once you have them should not belong to the same code base creating them.
While it would still be possible to keep references to you modules, or make them implement some interface (still pojos!) and call them to clean up themselves in onDestroy it would probably lead to more confusion than just doing the cleanup where others would expect 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

Application class lifecycle while service is running

I am developing an application with custom Application class which initializes a couple of singletons so they live during all application working time. I also have a couple of services in my application which work with these singletons. Is it possible situation that Application class will be destroyed by android with singletons' instances before services so services will not be able to use them? Or application lives always even for services of it's context? What is the best way to find a way out of this situation?
Thanks.
Regarding the application object:
The application object is the main absolute starting point on any Android app. It will always exist before any of the Manifest declared items such as Activity, Service and BroadcastReceiver. So relax that the singletons will be there for you.
Regarding the singleton paradigma:
That's a big discussion topic, you can google more about it so what follows is my personal opinion on it. Whatever is the reason for your singletons (a database, an bitmap caching, a FileUtils) I think it's ok and correct to initialise them on the very first point of entry of your app, which is the Application. But the application itself is not an object meant to carry or hold those objects, that way my suggested design approach is to:
=> on your singleton object/class you'll have to:
private static MySingletonClass instance; // reference to the single object
private MySingletonClass(Context c){ // private constructor to avoid construction from anywhere else
// let's say it needs the context for construction because it's a database singleton
}
public static MySingletonClass get(){ //
if(instance == null) throw new RuntimeException("This singleton must be initialised before anything else");
return instance;
}
public static void init(Context c){ // call the initialisation from the Application
instance = new MySingletonClass(c);
}
=> and then on your Application object you simply init the singleton
onCreate(){
MySingletonClass.init(getApplicationContext());
}
with that way you'll keep the necessary initialisation, enforce the singleton pattern but to access the object you call to that object class not to the application. I know it's just a organisational difference, but I believe that that's what separate good and bad code.
So for example on your service the call is: MySingletonClass.get() and should never be MyApplication.mySingle.
hope it helps.
From my understanding service can't live without application context, service is bound to the application with the Context reference so I think if the application is killed also the Context is killed and that lead that all components are been killed,
you can read here for more info
http://developer.android.com/guide/components/fundamentals.html#proclife

Lifecycle of enum based singleton on Android

A few days ago I've discovered that singleton can become anti-pattern in Android. My singleton (class with private constructor and instance stored in static field) was deleted (instance was deleted despite the fact other activities were still using this singleton (via getInstance() method) so another instance had to be created ) because Activity from which it was first invoked was deleted (after invoking finish for only this one activity).
I've read already how this problem can be resolved however I've also just read "Effective Java". There is said that "Single-element enum type is the bast way to implement a singleton".
So now I'm wondering what would be the lifecycle of singleton created this way in Android application? Would it be the same like in case of "standard singleton implementation" so after destroying activity from which it was invoked the first time it will be destroyed (even if it used also in other activities)?
I'm not asking about proper android singleton implemenation or the singleton pattern itself (is it pattern or anti-pattern etc) but I'd like to know what be the lifecycle of such enum singleton object and when it will be destroyed.
In all cases, the classes you use are tied to the ClassLoader that loaded them. This is true in Java in general, not just Android. Android will isolate activities by using new ClassLoaders each time -- at the least, it doesn't promise it won't, and it does as far as I can tell.
Any singleton, or other class-level state, is tied to the Class which is tied to the ClassLoader. This is why your state "disappears"; it's actually that your calling code is seeing a new Class in a new ClassLoader.
So, your enum-based trick, or anything else along these lines, would have exactly the same behavior. You just can't "persist" activity information this way. You can and should write to a SQLite DB. You could probably stash it in the SharedPreferences too.
The application object is a good location to store information which needs to be accessible to various activity or service instances. You can retrieve it like this (where this is an Activity or Service):
private MyApplication app;
in onCreate(...){
...
this.app = (MyApplication) this.getApplication();
...
}
Remember to set the name also in the manifest:
Set the attribute "name" of the "application" tag:
The value is the path to the class relative to the package of your app.
The application object is created when the app is started, you can initialize like in an activity or service in it's onCreate() method.
One thing to remember: The application object can survive closing your "last" activity. In this case you may get the same application object with the state from the previous interaction with your app. If this is a problem you must somehow detect the initial start of your app (e.g. using a special launcher activity without UI, which initializes the application object and then starts a new intent.
BTW, the same may happen with singletons if they have not yet been lost to garbage collection.
My secure singleton implementation is like that:
I create a singleton class which has an attribute of boolean 'didReceiveMemoryWarning';
public class SingleTon(){
public boolean didReceiveMemoryWarning = true;
...
...
}
In application first screen(It is exactly first launch screen)(I have a splash screen that is visible 3 sec)
SingleTon.getInstance().didReceiveMemoryWarning = false;
And in every Activity's onCreate() method, check this boolean data,
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(SingleTon.getInstance().didReceiveMemoryWarning){
{ Load your data from local to your SingleTon class,
because your app was released by OS};
}
}
it is my implementation.

Categories

Resources