I'm making an Android app that will have the timetables of a local bus.
There are more than one timetable, the one that will be use depends on the day.
If it's a holiday I must use a special timetable, so I want to know when is a holiday and when is not.
The thing is that I'm creating a class that will handle this, it will try to retrieve information from memory or from a web api. Then some other classes will be able to communicate with this class, but it doesn't seem necessary to me to have more than one instance of this class, I could create just one instance and share it with the rest of the classes.
Could this class be a Singleton or it would be better if I create a normal class ?
In your case (retrieving info from memory), definitely avoid using a singleton class because it will highly likely be tied to your Activity context.
Your class will have a static reference to a class, therefore
it will be kept in memory when not needed.
singleton may be reinstantiated, or may use obsolete instance, with new instations of activities. You will lose control of the current variables.
diffent instances of the same activity class are highly likely to conflict with this class.
Examples of the same activity class several instantiation:
Change device orientation.
Running app from the webbrowser's, Google Play, file browser intent.
Besides, at some point, when you add functionality based on user reviews, your app will grow, you are likely want to refactor your class, break it into subclasses, put some of its methods into separate threads. It will no longer be easy to do.
It might seem fun while the app is small, and untested, but later, in Android specifically, you will run into a nightmite with unpredictable and hard to detect errors.
Because of Android's special way to recreate activity class, through onCreate, onResume etc. you will run into a nightmare, when the app will start living its own life.
You will no longer be able to rely on the assumption that the current singleton instantiation actually belongs to your current activity.
You may swap between orientations or run your app from different entry points (launcher, recent apps, google play), and it may reuse the variables actually prepared for a different activity instantiation.
If you need only one instance of the class, just create one instance of the class in the onCreate method - and that will make the app much more manageable.
One of the main advantages a Singleton class brings you is the fact that you are sure to have one and only one instance of an object doing some thing, and that it is instantiated only once (preferably at a specific point of your application, for instance at startup or only after certain other operations have been performed)
An example could be for instance a cache implementation: you want to make sure that all classes that need a certain cache read and write from the same object, that maybe is created and filled with information at startup time.
Your does not seem to be the case, unless you fetch the information you need when your application starts and then you keep them memorized for some reason: in this case you want to make sure your information is fetched one and only one time, to avoid wasting memory and elaboration time. Also, a Singleton is fine if you need to do some kind of operation when your class is instantiated, like opening a connection that then stays open.
On the other hand, if you just need a class with some method to call some external apis or database and you don't need to memorize any information in it, there is no reason to initialize a singleton.
If this is your case, why don't you try some static class/methods? They can be called like normal methods directly on the class with no need to instantiate objects or keeping a state, saving memory and avoiding side effects.
Related
Developing a jogl application, this is (a part of) our core class structure
main jFrame
viewer (for rendering)
inputListener
viewpole (for camera/projection control)
graph (holds nodes/meshes)
icon handler (to expand/collapse a node with children)
So if I want to call methodX() in the icon handler(that is basically the texture representing the handler, it is the same for all the nodes), I have to call:
Main.instance.getViewer().getGraph().getIconHandler().methodX()
where instance is a static variable holding the instance of the main jFrame
Given they are all:
1) instantiated once
2) at the begin
3) are supposed to be there for the whole time
4) in theory, no problem of race conditions, we are using java.util.concurrent.locks.ReentrantReadWriteLock at lower level when we add/read/modify/delete nodes
is it dangerous/bad design assigning the instance of each class to a static variable inside each corresponding class?
so that if I want to access the same methodX() I would just call
IconHandler().instance.methodX()
Ps: I read some of the other questions regarding static variables() but I found them quite generic, mine regards the core parts.
As long as you know that you'll only ever need one instance of each class, this is okay. This is called a singleton and is a pretty well-known design pattern.
The problem is that you probably can't guarantee that you only need one instance of your classes. Singletons are good for things like data connections or file readers, where there is a built-in limit to the number of instances that should access the data.
You're misusing the static keyword as a lazy way to gain access to an instance of a class, and it's going to come back and bite you when you expand your program to include multiple instances of those classes. And if you think you'll only ever need one instance- you can't guarantee that will never change.
I need to access a few of my custom objects in different activities of my application. For this purpose and for the sake of accessibility I have been using static properties for moving data from an activity to another.
For example I have the following class:
public class TrackItem {
public String title, imageUrl, mediaUrl, type, artist, desc;
public static TrackItem track;
}
And for starting an activity:
TrackItem.track = items.get(i); // 'items' is an arraylist defined elsewhere
Intent trackActivity = new Intent(c, TrackActivity.class);
startActivity(trackActivity);
And now inside the TrackActivity I can easily access TrackItem.track and use it's properties.
I just need to know if I'm making a mistake or not? Is there any better way to do this?
The android way of dealing with that problem is to make your class
Parcelable
and pass it with the intent from one activity to another.
If you are initializing your static variables in an activity be aware of loosing data, because in android activity can be destroyed at any point after its state changed to pause. Moreover, your static variables can be erased if the entire application is killed by the system, that is happening rather frequently. Then you'll get the
NullPointerException
trying to access your data.
If you really want to use static members handle their initialization in the
Application
class constructor, so they will be recreated on the start of your application, being killed.
But in general it is not a good practice in android.
I would say it is OK in certain cases, but there might be other more suitable solutions.
You could have a central data store class that uses the singleton principle and therefore would be accessible from everywhere. You would add the item id to the Intent for the new Activity. Then, with the id, you could get the item from the data store.
You could also make the item serializable and just add it to the Intent.
One thing to keep in mind when using static members is that it could lead to a memory leak. Static members are related to the class and are therefore only garbage collected if you either set them to null, or the whole app gets killed and the classloader unloads this specific class.
In general, this is an unsafe practice because it is difficult to keep track of who is manipulating its data. It is much safer to use static variables for bookkeeping information, such as an ID which you can use to go look up the appropriate TrackItem (e.g. in an SQLite database), which is its own object and does not have the chance of something else editing it when it shouldn't be. It terms of OOP, using static variables as shared data breaks encapsulation.
If you are looking to send data around the app, it would be much better to do so either with intents, as others are saying, or with SharedPreferences. Both have the advantage that you are dealing with only one instance of the object at any given time, SharedPreferences have the added advantage of keeping the data around after the app has been killed, so that users can resume with the same track that was playing when they closed the app. And both of these are safer than using static members as shared data fields.
This might not make much sense in terms of Android SDK, but, in C++ I am used to keeping my main.cpp (and specifically main() function) as a place where I declare and initialize other classes/objects, and afterwards all the things that my application does take place in those classes. I never come back and check for anything in main.cpp afterwards.
But in Java, Android SDK, you have to override dozens of methods in main activity and all of that takes place in one single file. Example:
I have a MainActivity.java and SomeTest.java files in my project, where first is default MainActivity class which extends Activity, and SomeTest.java contains class that declares and runs new Thread. I initialize SomeTest class from MainActivity.java and pass a handle of the activity to it as a parameter:
SomeTest test = new SomeTest(MainActivity.this);
And having the handle to MainActivity, I proceed doing everything from this newly created thread. When I need to update the UI I use runOnUiThread() to create and show a new ListView (for example) on my main layout. I want to get the width and height of the newly created Listview, for what I have to override onWindowFocusChanged() in my MainActivity.java and notify the thread from there, as getWidth() and getHeight() will only have values when ListView is actually displayed on the screen. For me it's not a good practice to make such connections ('callbacks', if you will) from MainActivity to that thread.
Is there a way I can keep methods like onWindowFocusChanged() within the thread and don't touch the MainActivity.java at all?
As I said, might not make much sense.
Is there a way I can keep methods like onWindowFocusChanged() within the thread and don't touch the MainActivity.java at all?
onWindowFocusChanged() is a callback method. It is called on the activity. You cannot change this.
And having the handle to MainActivity, I proceed doing everything from this newly created thread.
That's generally not a good idea. Using a background thread to, say, load some data from a file or database is perfectly reasonable (though using Loader or AsyncTask may be better). However, usually, the background thread should neither know nor care about things like "the width and height of the newly created ListView".
You are certainly welcome to migrate some logic out of the activity and into other classes. You might use particular frameworks for that, such as fragments or custom views. However, the class structure should not be driven by your threading model. For example, let's go back to your opening statement:
in C++ I am used to keeping my main.cpp (and specifically main() function) as a place where I declare and initialize other classes/objects, and afterwards all the things that my application does take place in those classes
However, in C++, you would not say that you are locked into only ever having two classes, one of which is operating on some background thread. While you may have a class or classes that happen to use a background thread (or threads), the driving force behind the class structure isn't "I have a background thread" but "I want to reuse XYZ logic" or "I wish to use a class hierarchy in support of the strategy pattern" or some such.
Personally speaking Context idea taken from Android SDK seems to be messy. What you are describing comes from too much responsibility intended for Activity. That's why you need to track a LOT of things inside single file (Activity's life cycle, getting Context instance in order to show Dialog etc.). I don't think there's perfect solution but I would recommend using:
Fragment subclasses which are helping to divide your screen (and so on logic) into seperate parts
3rd party frameworks/libraries like AndroidAnnotations, RoboGuice, Otto which are perfect tools to avoid spaghetti code
if you would like to perform some UI updates from another class, consider using an AsyncTask passing it the Views you need to update. Let me know if you need an example
I read everything and understand your statements, I can see you've been doing programming for sometime but apparently is just starting with Android, I've done a lot of embed systems before so I totally get the concept of having a software that looks like:
void run(){
object.setup();
while(true){
otherObject.run();
}
}
But there's one fundamental flaw on the you logic of your question:
Android programming is a different programming paradigm from C++ and from computer programming and you should understand its specific paradigm instead of assume what is good practice from other paradigms.
Quote from you: create and show a new ListView (for example) on my main layout. I want to get the width and height of the newly created Listview, for what I have to override onWindowFocusChanged().
From that I can see that you've really trying to do Android stuff on a way that is not recommended on an Android context. A ListView you can easily implement from the XML layout setContentView(int) and use the Activity onCreate to instantiate any threading (AsyncTaskLoader) framework to load the data in background and deliver it back to the UI.
That doesn't mean that all your code will be dumped in one file making it a mess. This little example I put you can do with Activity that implements the loader callbacks, a separate class with the loader, a separate class with the data loading work, a separate class with the data adapter, the activity is just a central piece that organise and manage those classes on the correct moment of its life-cycle and at no point you need to call onWindowFocusChanged() and still have a nicely organised code.
Apart from that please refer to CommonsWare answer as it's usually cleverly written and correct.
two classes extend Application
One class I've registered in the Manifest and am using as an Application is meant to be
Second class is my utilities class. It does lots of I/O and has a few helper methods. For I/O you need context (getAssets etc), so I reluctantly extended Application.
Note:
Everything is working as it should.
My Question:
Are there any drawbacks of using multiple Application classes? Is this even advised?
A few thoughts:
Like what would happen if I had onCreate and other callback methods defined in both the classes?
How do I register them both in the manifest even?
etc
PS: I know I can just use a field to store context in the second class.
I think this is not advised at all, because there is could only be one instance on Application (thus only one class).
I am very suspicious about what is really working. You're talking about utility class, so maybe you're using static methods that are working well. But you should use your debugger, and I'm almost certain that you'll discover that one of your classes is never instantiated.
By the way, the official documentation states that :
" There is normally no need to subclass Application. In most situations, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton. "
I'm starting with Android and wonder if background Task like DB reading and saving are always encapsulated in private classes?
I mean, at the moment I have:
private class SaveToDB extends AsyncTask..
private class ReadFromDB extends AsyncTask..
public void onButtonClick(View v) {
new SaveToDB().execute();
}
And so on. This way, I always have to create a new object if I want to execute background tasks. Is that the correct way?
What I wonder is that all my private classes are "actions" itself, not really objects. As they are named eg save or read which naming normally applies to methods by convention, not to classes.
Moreover, in case I'm doing it right: is it good practice to neast the private classes inside MyApplication Activity? Or should I refacter them out into own separate classes?
You could write a service to handle all the background content management. So, when you want to save, you just message the service and tell it to write data. This is much more complicated. For simple things, you can do it exactly as you are currently.
EDIT:
Also, as Ian pointed out, take a look at the new database interfacing classes post 3.0.
If you are firing of async tasks to interact with a sqlite database, then its not the best way to do things these days, you should check out cursor loaders instead.
http://developer.android.com/guide/topics/fundamentals/loaders.html
http://developer.android.com/reference/android/content/CursorLoader.html
Once you got your head around them they are much easier than firing off async tasks, infact they build on top of async tasks to address some of the issues you describe and are tolerant to configuration changes.
I highly recommend to move away from AsyncTask (for db access) and use the Loader API instead.
Its backported in the compatibility package so you can use them in older versions prior to Honeycomb.
Not always.
For example, if you've got a task that is to be used by different activities (I'm not talking about sharing the same instance), you will want a public class so you don't write it several times.
If you only use that (class of) task in one place, private class might help keeping your code cleaner.
It is a correct way for using AsyncTask, which isntance you can execute once.
Class Name can be DbSaver isntead of SaveToDb for instance which is more readable.
If that class is used only one Activity you can nest them, why not. But if you have task which is executed within different Activities, it is a good idea to create his own file.
It is good design to loosely couple your database access from your UI code. One way to avoid having to create a new object every time would be to make the database access classes a singleton and just return the instance of the class whenever you need to make a transaction.
To your last question it is a better idea to move the database management to its own class so that it can be accessed across several activities. If you do it all in a private class then what happens when you have a new activity that need s database access?