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.
Related
So here is a very standard task in Android: load data from the server and display it on the screen. One of the biggest problems is, of course, handling configuration changes. For example, when loading is started and device is rotated, the loading must not be started again and loading progress must still be shown.
Now, there is a ridiculous number of ways people approach this basic problem. Let's say, we use the Model-View-Presenter pattern. A lot of solutions revolve around saving Presenter, entirely or partially (in the View's bundle, in a Singleton or any other way), to not lose data on rotation. Others involve Retained Fragments and AsyncTasks. And I quite rarely encounter a solution that uses a Singleton to perform loading data! Why is that?
Here's the way I think it can be easily done. We make Presenters "light" and not perform any state saving, and handle data loading in a Repository that is a Singleton. When device is rotated, the newly created Presenter can just get current loading status from the Repository, update its View accordingly and, if data is loading, resubscribe to the Repository (via callbacks or RxJava Observable) to get notified when data is loaded. As for the Repository, it can easily load data in the background with the help of RxAndroid. So, isn't it easier to handle all data loading business in one place and not worry about activity's lifecycle?
This way we basically skip the whole configuration change problem. There are only a couple of things I see that must be handled carefully:
Activity leaks in the Singleton. To prevent this we just have to unsubscribe Presenter from the Repository when its View gets destroyed.
Testing, as it is harder to test a Singleton. But this is not an issue if we use Dagger - in this case we can test out Repository like any other class.
So my question is this: why is this approach (performing data loading in a Singleton) is not a common solution? What am I missing?
I seriously recommend you read up on a library specific for the purpose of network requests, rather then trying to reinvent the wheel and having to deal with all the pitfalls which might arise.
Recently I've been trying out RoboSpice. If you read up on their page below, you'll see that it "executes network requests asynchronously (in a background AndroidService)", precisely to avoid memory leaks.
I say, give it a try! Lots of projects in my workplace make use of RoboSpice and they all work pretty well.
https://github.com/stephanenicolas/robospice
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
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
This pattern is similar to the pattern Main Servlet (the Front Controller) that is used for developing web applications.
The main idea of this pattern: we have one Activity that manages multiple views and this activity is responsible for representing current content. Not all views need functional of activity (e.g. life-cycle methods) so the main question is: if I can go without activity why do I have to use it?
I have found the following disadvantages of using this pattern:
Official source doesn't recommend to Overload a Single Activity Screen
but they don't explain why.
We cannot use TabActivity, ListActivity, MapActivity. But there are some tricks to go without them.
If different screens have different menu it's a problem to make that without activities.
It is necessary to keep history by ourselves. But it's not so difficult to develop.
I have found the following advantages of using this pattern:
It's faster to change the content of current activity than to start another activity
We are free to manage history as we want
If we have only one activity-context it's simpler to find and solve problems with memory leaks
What do you think about this pattern ? Could you provide any other advantages/disadvantages ?
We cannot use TabActivity, ListAcivity, MapActivity. But there are some tricks to go without them.
You have to use MapActivity if you want to use MapView. You have to use PreferenceActivity if you want to use preference XML.
It is necessary to keep history by ourselves. But it's not so difficult to develop.
The difficulty in managing your own history will depend greatly on what the history needs to be. Implementing history for a simple wizard will be fairly easy. However, that is a particularly simple scenario. There is a fair amount of history management code in Android that you would have to rewrite for arbitrary other cases.
You also forgot:
#5. You will be prone to leak memory, because you will forget to clean up stuff, and Android will not clean up stuff (since it assumes that you will be using many small activities, the way they recommend).
#6. Your state management for configuration changes (rotation, dock, SIM change, locale change, multiple displays, font scale) will be more complicated because now you also have to figure out what extra stuff (e.g., history) need to be part of the state, and you have deal with all of them at once rather than activity-at-a-time.
#7. Having multiple entry points for your application becomes more challenging (e.g., multiple icons in launcher, app widget linking to some activity other than the main one, responding to etc.).
It's faster to change the content of current activity than to start another activity
For most modern Android devices, the speed difference will not be significant to most users, IMHO.
If we have only one activity-context it's simpler to find and solve problems with memory leaks
Except that you still have more than "one activity-context". Remember: your activity, large or small, is still destroyed and recreated on configuration changes.
What do you think about this pattern ?
Coase's "nature of the firm" theory says that businesses expand until the transaction costs for doing things internally become higher than the transaction costs for having other firms do the same things.
Murphy's "nature of the activity" theory says that the activity expands until the transaction costs of doing things internally become higher than the transaction costs for having other activities do the same things. Android developers will tend towards a "user transaction" model for activities -- things that are tightly coupled (e.g., steps in a wizard) will tend to be handled in single activity, and things that have little relationship (e.g., browse vs. search vs. settings vs. help vs. about) will tend to be handled in distinct activities.
This will be horrible to maintain if new functionality is added later on.
I'm also not convinced it will be so much faster that the user could notice.
Having components as smaller pieces that are easier to change or swap out is definitely the way to go.
I just read a pretty interesting article on how android (and i assume other OSs) work when low on memory. How is this done theoretically? Is it similar to Java's object serialization?
In a word: yes.
In a few more words, sort of. You have to handle more of it manually than personally I'd like. Essentially, all Android provides for you is a hash to shove a few serializable objects, referenced by strings, that is guaranteed to be safe across application shutdowns. So, whenever something happens that you'd like to preserve across a shutdown of your application, you are responsible for updating this saved state hash (and letting Android know that you've done so). This includes things like half-finished text entry in form fields. That means you have a lot to listen to.
Android will then call a particular hook in your Activity that handles restoring state to the Activity when it recycles your application and you need to do so. This doesn't happen for all recycles — there are various states of being/existence for your application.
The screwy part is that because you're expected to do this sort of tedious work anyway, Android gets lazy and implements things like screen rotation as a full recycle of your application.
I'm making it sound worse than it really is once you get used to it; it's really not a bad way of solving the problem in the confines of Java and mobile computing.
Of course, this is a response regarding Android. Other (desktop) OS's rely on Virtual Memory and Paging to deal with memory constraints.