I find that using application class to store some shared variables or to get to things like PACKAGE_NAME or OS version via methods quite useful. This is because in this way you can get to this data from any component in your app and you can store objects that exist while your app is loaded, thus you avoiding some of GC and lifecycle problems. Although useful if used sparingly this seems like an antipattern to me. Because basically application class is doing too much.
What I would like to know is what are your thoughts about this and should this approach be discouraged in favour of Persistent headless Fragment or some other approaches?
Yes, the application object is a god object and therefore an anti pattern.
However, as with all patterns there are pros and cons.
Pros
Quick to use the application object as a god object
Cons:
Difficult to effectively manage the lifetime of data in the application object since the application object is bound to the lifetime of your application
Difficult to properly unit test an Android activity or fragment which is heavily coupled to the application object
If you're using the application object to store information that is specific to one or two screens, eventually the object will become a hodgepodge of what is effectively unrelated information, and therefore difficult to manaage
Related
It seems to me that if you have some state or data in android that you want to access from different activities (but don't want to persist) you need a singleton. Is this correct or are there other ways to design an application?
It is not that I have a problem with singletons. I am just wondering because this is so radically different from normal desktop application development.
What you said is definitely not correct and there are other ways to design an Android app.
Actually, for Android development, Singletons should be avoided or used sparingly and should not be used as the first or only solution. It should especially not be used to carelessly share data or state across Activities.
If you find your app requiring the use of Singletons for everything, then chances are... you're in need of a redesign for your app.
When using Singletons, there are actually a few things to keep in mind:
They typically live throughout the entire lifecycle of the App until they're closed by the system closing your app
Improperly created Singletons can easily leak memory
Improperly designed Singletons and excessive use of Singletons can use up a lot of unneeded memory
They're hard to use for testing
Overall, when using Singletons, you really need to think about if there's a sufficient need for that part of your app to be a Singleton.
For most situations, the answer is no. In the cases you mentioned, such as accessing state or data between Activities, it's a yes and no.
It's a yes because the need to access data might warrant the use of a Singleton. It's a no because the need to access the state of the app shouldn't.
Your use of the word 'state' is a quite unclear, but Activities should really be self-managed, since the state of an Activity shouldn't interfere with the state of another Activity. If it does, there are better ways to send that information to the Activity (such as using Intent extras) rather than creating a Singleton that is accessible for everything and existing for longer than it should.
There really is very few reasons to warrant a need for a Singleton.
In my experience, there are only two reasons that might allow for the use of a Singleton:
The real need for a single instance to exist
The Singleton is used very often and it's expensive to constantly create it, but there won't be any major side effects to keep it in memory.
For example, an SQLite Database is commonly used as a Singleton because a single synchronized instance of the database can help prevent more than one Activity or Service from reading/writing to the database. This helps prevent situations such as one object writing new data, while another object reads old data before the new data is written. Or the simple situation of two objects writing different data to the same field at the same time.
Additionally, an SQLite Database is also accessed very often by apps, so it doesn't make much sense to constantly open a database, fetch some data, close the database, open a database, write some data, close the database, and repeat.
I've seen developers use Singletons for a lot of situations, and most of them for really bad reasons.
The Good:
Databases
SharedPreferences (the app needs to access preferences way more often than normal)
Logging system
The Bad:
I saw a developer load up a large amount of Drawables and stored it in a Singleton upon starting his app... just so he could quickly use those drawables everywhere.
I saw some developers using Singletons to hold a list of created Activities, so they could access those Activities methods and views... (dead)
I've seen more bad stories, but I can't recall them now.
Also, keep in mind that even though I said things like Databases are a good idea to be used as a Singleton, I only meant it has the needs to warrant the use of a Singleton. A database doesn't need to be a singleton and there are other solutions available that might fit your app better.
So always think about whether there's a need for you to use a Singleton.
In your case, does the state/data you need to access by other Activities really need to stay alive for the duration of the app and can it be solved through solutions like: SharedPreferences, Intent extras, Callback Interfaces, Databases, static classes/fields/methods, and etc.
If you've thought out your app well and really think a Singleton will benefit your app best, then use it. Don't forget to use an Application Context instead of the Activity's Context, because the Singleton will definitely outlive your Activity and you don't want memory leak issues.
I am currently trying to learn the principles of redux/flux and how they can be implemented in Android. What don't I get is how the principle of only one global store/state should be implemented in an Android application? Are there any best practices for this, especially regarding saving and restoring after orientation changes and after the Android system decided to free up memory?
The only solution I thought is applicable is using the ViewModel Class from the Android architectural components. But that isn't really a global state, only per Activity.
You can try to keep the state in the application class. This will survive context changes, and terminate together with the application.
If you don't want to bother with extending the application class then a global static class/reference will do.
When passing data around in Android (between Activities, for example), it seems that the primary accepted method is to use Bundles and Parcelables. The problem with this approach is that it serializes all the data, which is inefficient. I'm wondering - is there way to pass around references rather than the data itself for efficiency?
This may be less efficient (though should not be a big impact in most cases) but avoids keeping a references to object between activities. That helps to keep the architecture cleaner and with less prone to memory leaks.
You can use Application class, static helper classes, singletons or services in some cases to help you but make sure you know what you're doing with them.
I would say your best approach would be to make all data model objects parceleble, and make all activities extend a base class and use a wrapper or a helper method to pass your data model objects between activities.
I use this approach in all my applications and thus far it has been very helpful and minimizes the number of references used between activities and fragments.
There are a number of techniques you can employ, it all depends on what you are trying to achieve, for example you can use a singleton to keep a reference alive, or you may (although you really shouldn't) use a static reference. In the end it all comes down to what kind of data are you trying to pass around.
Remember that sometimes is better to rebuild an object, than it is to keep it alive until (if it ever happens) the garbage collector clears it.
I like to use the singleton design pattern.
http://en.wikipedia.org/wiki/Singleton_pattern
Suppose you have multiple activities in an app and need to share data. A pretty common pattern for Android developers it seems is to have some sort of singleton object (optionally attached to the Application singleton), and share data globally using that. That's bad enough in Java, but looks really ugly in Scala.
For message passing you can use Intents if your data consists of primitives. But what about your main domain model? I'd like to be able pass very complex objects. It seems I might be able to do that using Parcelable serialization, but I'm not sure how fast that is (my objects are data-heavy) and if it works well with Scala? Has anybody tried this?
Another idea would be to use the "HashMap of WeakReferences to Objects" strategy where the passed messages are references -- you've still got global data but access is guarded. Maybe I can get some opinions on that too, not just from Android folk but also some Scala folk.
The way I solved this was to include the Akka library in my app, and turn the global objects into messages that are passed between activities.
It seems to work OK, but not a lot of people are using Akka on Android so far and it's difficult to find best practices. If people have any comments about this strategy, let me know.
I'm starting Android app development and just after my very first app more complex than Hello World I found out that you cannot hold any state in Activity because Android will recreate them in some cases... ouch, failure.
I'm guessing that strict model separation from view is a common practice, even for simple apps. Are there any settled patters I should follow? Some variant of Model-View-Controller?
You should definitely read the Application Fundamentals Dev Guide
In my experience, my design patterns in Android have been driven by the use of Intents, Activities, Services, Broadcast receivers and so forth.
I wouldn't say that "strict model separation from view is a common practice". You can keep data inside an Activity, but you will be forced to preserve it. Luckily this is made trivial by methods like onSaveInstanceState and onRestoreInstanceState where persistent data members can be saved to a Bundle and then retrieved from the same Bundle.