Furious Logic
Furious Logic

Reputation: 48

Android Activity Refreshing On Rotation

I'm an experienced .NET dev, but this is my first Android app and it's driving me nuts!

It's a countdown timer which works fine, but when you rotate the screen it reinitialised the activity which zeroed and stopped the count down.

This is what I tried; I got rid of the CountDownTimer object and instead created a class internal to the activity which extended AsyncTask so it ran on a separate thread... No change. I figured being an internal class it's being reinitialised with the activity.

Here's what I tried next; I made the class an external one. The Activity passes its Context to the class and the onProgressUpdate & onPostExecute run public functions on the context to update the activity's UI. Again, this works fine until you rotate it... Aaaargh!

However, I discovered that the async class is still running but the UI doesn't change because (I think) the activity now has a different context to the one the async class has reference to.

So that's where I am. Each solution fixes one problem & creates another. Do I need to somehow maintain the context or am I starting to chase my own tail?

Any help will be gratefully appreciated!

Ta. Barry

Upvotes: 3

Views: 183

Answers (3)

ci_
ci_

Reputation: 8774

In your CountDownTimer implement onTick:

@Override
public void onTick(long millisUntilFinished) {
    // something like this:
    this.millisUntilFinished = millisUntilFinished;
}

In your Activity implement onSaveInstanceState:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // something like this:
    savedInstanceState.putLong("millisUntilFinished", millisUntilFinished);
}

also in onCreate and onStart re-setup your CountDownTimer:

@Override
public void onCreate(Bundle savedInstanceState) {
    // ...

    if (savedInstanceState != null) {
        millisUntilFinished = savedInstanceState.getLong("millisUntilFinished");
    }

}

@Override
public void onStart() {
    super.onStart();
    timer = new MyCountDownTimer(millisUntilFinished, 100); 
    timer.start();
}

Don't copy this code verbatim, there are a few details missing/assumptions made that will be different in your code, but it could look something like this.

Upvotes: 2

kauron
kauron

Reputation: 95

The solution from Try_me34 is good, but here are some other ways to save and restore data (can't post them as a comment):

Try overriding the onPause method and save the process to a secondary class (a Timer, maybe) and then restore it overriding onResume.

Another option is to save it as a preference:

SharedPreferences.Editor editor = getSharedPreferences("nameOfFile", MODE_PRIVATE).edit();
editor.putInt("name", value);
editor.putString("nameForString", value);

And then load it:

SharedPreferences prefs = getSharedPreferences("nameOfFile", MODE_PRIVATE);
int i = prefs.getInt("tag", 0);
String s = prefs.getString("tag", "defaultValue");

Upvotes: 1

Menelaos Kotsollaris
Menelaos Kotsollaris

Reputation: 5506

However, I discovered that the async class is still running but the UI doesn't change because (I think) the activity now has a different context to the one the async class has reference to.

Nice guess. You have to handle the Activity's lifecycle, if you want to keep the computed data since whenever you rotate the device, the activity is getting recreated thus onCreate() is getting called without saving the previous computed data. You have to override onSaveInstanceState(Bundle savedInstanceState) and onRestoreInstanceState() in order to save your computations. Take a look at the Activity's LifeCycle documentation and Reto Meier's answer, I think it will solve your problem.

Upvotes: 1

Related Questions