There are several differences between HashMap
and Hashtable
in Java:
Hashtable
is synchronized, whereas HashMap
is not. This makes HashMap
better for non-threaded applications, as unsynchronized Objects typically perform better than synchronized ones.
Hashtable
does not allow null
keys or values. HashMap
allows one null
key and any number of null
values.
One of HashMap's subclasses is LinkedHashMap
, so in the event that you'd want predictable iteration order (which is insertion order by default), you could easily swap out the HashMap
for a LinkedHashMap
. This wouldn't be as easy if you were using Hashtable
.
Since synchronization is not an issue for you, I'd recommend HashMap
. If synchronization becomes an issue, you may also look at ConcurrentHashMap
.
You need to override onSaveInstanceState(Bundle savedInstanceState)
and write the application state values you want to change to the Bundle
parameter like this:
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putBoolean("MyBoolean", true);
savedInstanceState.putDouble("myDouble", 1.9);
savedInstanceState.putInt("MyInt", 1);
savedInstanceState.putString("MyString", "Welcome back to Android");
// etc.
}
The Bundle is essentially a way of storing a NVP ("Name-Value Pair") map, and it will get passed in to onCreate()
and also onRestoreInstanceState()
where you would then extract the values from activity like this:
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}
Or from a fragment.
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}
You would usually use this technique to store instance values for your application (selections, unsaved text, etc.).
Best Answer
There are many ways to download files. Following I will post most common ways; it is up to you to decide which method is better for your app.
1. Use
AsyncTask
and show the download progress in a dialogThis method will allow you to execute some background processes and update the UI at the same time (in this case, we'll update a progress bar).
Imports:
This is an example code:
The
AsyncTask
will look like this:The method above (
doInBackground
) runs always on a background thread. You shouldn't do any UI tasks there. On the other hand, theonProgressUpdate
andonPreExecute
run on the UI thread, so there you can change the progress bar:For this to run, you need the WAKE_LOCK permission.
2. Download from Service
The big question here is: how do I update my activity from a service?. In the next example we are going to use two classes you may not be aware of:
ResultReceiver
andIntentService
.ResultReceiver
is the one that will allow us to update our thread from a service;IntentService
is a subclass ofService
which spawns a thread to do background work from there (you should know that aService
runs actually in the same thread of your app; when you extendsService
, you must manually spawn new threads to run CPU blocking operations).Download service can look like this:
Add the service to your manifest:
And the activity will look like this:
Here is were
ResultReceiver
comes to play:2.1 Use Groundy library
Groundy is a library that basically helps you run pieces of code in a background service, and it is based on the
ResultReceiver
concept shown above. This library is deprecated at the moment. This is how the whole code would look like:The activity where you are showing the dialog...
A
GroundyTask
implementation used by Groundy to download the file and show the progress:And just add this to the manifest:
It couldn't be easier I think. Just grab the latest jar from Github and you are ready to go. Keep in mind that Groundy's main purpose is to make calls to external REST apis in a background service and post results to the UI with easily. If you are doing something like that in your app, it could be really useful.
2.2 Use https://github.com/koush/ion
3. Use
DownloadManager
class (GingerBread
and newer only)GingerBread brought a new feature,
DownloadManager
, which allows you to download files easily and delegate the hard work of handling threads, streams, etc. to the system.First, let's see a utility method:
Method's name explains it all. Once you are sure
DownloadManager
is available, you can do something like this:Download progress will be showing in the notification bar.
Final thoughts
First and second methods are just the tip of the iceberg. There are lots of things you have to keep in mind if you want your app to be robust. Here is a brief list:
INTERNET
andWRITE_EXTERNAL_STORAGE
); alsoACCESS_NETWORK_STATE
if you want to check internet availability.Unless you need detailed control of the download process, then consider using
DownloadManager
(3) because it already handles most of the items listed above.But also consider that your needs may change. For example,
DownloadManager
does no response caching. It will blindly download the same big file multiple times. There's no easy way to fix it after the fact. Where if you start with a basicHttpURLConnection
(1, 2), then all you need is to add anHttpResponseCache
. So the initial effort of learning the basic, standard tools can be a good investment.