3
I have an Activity with only one timer basically, and when turning the phone, the chronometer is reset.
Is there an event that causes Activity to restart while doing so? I would like to prevent this behavior.
3
I have an Activity with only one timer basically, and when turning the phone, the chronometer is reset.
Is there an event that causes Activity to restart while doing so? I would like to prevent this behavior.
5
When you change the orientation of the device, Android destroys and recreates the Activity
. What’s going on is that you’re probably starting your stopwatch on onCreate
. Like the onCreate
is being called again, the status your timer is being restarted.
What you should do will solve not only the rotation problem but the problem of when your Activity is destroyed in the background because the system needed memory (you can simulate this situation by enabling "Do not keep activities" in the device developer settings)
I imagine your code goes something like this:
public class CronometroActivity extends Activity {
// ...
// campos da sua classe
// ...
private Cronometro meuCronometro;
// ...
// mais campos da sua classe
// ...
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
// inicialização dos elementos da tela
// ...
this.meuCronometro = new Cronometro();
atualizarCronometroDaTela();
}
// demais métodos
}
Maybe you don’t have a Chronometer class, but other simpler variables to compose the chronometer state, but the principle is the same.
You must override the method onSaveInstanceState
of Activity
, which is called when the Activity is destroyed by the system. The system sends to this method a Bundle
, called here from estadoDeSaida
, within which you will put the data you want to persist between screen reboots. As you may already know, a Bundle
accepts data from Java primitive types, String
s, objects Serializable
and objects Parcelable
(among a few others).
Assuming here that the class Cronometro
implements Parcelable
, the code would look like this:
@Override
public void onSaveInstanceState(Bundle estadoDeSaida) {
super.onSaveInstanceState(estadoDeSaida);
estadoDeSaida.putParcelable("chaveDoMeuCronometro", meuCronometro);
}
After the recreation, the onCreate
will be called, and will be passed on to him that same Bundle
in the parameter savedInstanceState
, instead of null
which stays there when the Activity
is starting normally. From it, you should remove the data you had placed and recreate your stopwatch.
In this example, it would look like this:
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
// inicialização dos elementos da tela
// ...
if (savedInstanceState) {
this.meuCronometro = savedInstanceState.getParcelable("chaveDoMeuCronometro")
} else {
this.meuCronometro = new Cronometro();
}
atualizarCronometroDaTela();
}
That way, your Activity
is protected from the loss of this information and your timer will not reset.
However, in the specific case of the stopwatch, you may need a more ingenious solution to prevent the loss of seconds in which the stopwatch would be frozen, waiting for destruction and re-creation. This solution is for the simplest (and most common) case where this is not important.
1
Great solution Pablo Almeida, I used this same, with a Serializable object, so I did not need to implement anything of Parceable. But you have to cast the object on the return of onCreate...
@Override
public void onSaveInstanceState(Bundle estadoDeSaida) {
super.onSaveInstanceState(estadoDeSaida);
estadoDeSaida.putSerializable("chaveDoMeuCronometro", meuCronometro);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
// inicialização dos elementos da tela
// ...
if (savedInstanceState) {
this.meuCronometro = (Cronometro) savedInstanceState.getSerializable("chaveDoMeuCronometro")
} else {
this.meuCronometro = new Cronometro();
}
atualizarCronometroDaTela();
}
Browser other questions tagged android
You are not signed in. Login or sign up in order to post.
It remains to add that the class Chronometer has to implement Parcelable. However, the simplest solution would be to store the condition in milliseconds of the chronometer and the team current. When the Activity is recreated, the chronometer is recreated with a state equal to the sum of the recorded state and the difference between the team current and the team saved, thus avoid implementing Parceable and solve the problem of stopwatch.
– ramaral
@ramaral I came to say "assuming that Cronometro implements Parcelable". : ) I didn’t want to go into the details of how to do this because it would be a subject for another question. And it’s very interesting your idea of a solution. Simple enough, even giving a good result.
– Pablo Almeida
You’re right, I’m sorry, I didn’t understand that phrase.
– ramaral
No problem. :)
– Pablo Almeida
One more note in relation to my solution: it makes no sense to pass classes with behavior between activities, what must be passed is its state to, from it, recreate the new instance.
– ramaral
I’m not sure I understand. The way you said it, I understood that you were spending two timestamps, something like two longs.
– Pablo Almeida
But then you spoke as if you were failing to recommend the solution you gave. Or I got it wrong?
– Pablo Almeida
What I mean is that you should not pass the "chronometer object" but your state (value marked on the dial).
– ramaral
In my head,
Cronometro
is an object that contains only the data. Anyway, it has some reference resource on this principle that you mentioned?– Pablo Almeida
I saw Chronometer also with behavior, like:
start()
,stop()
,reset()
etc. Why pass (in this case) the whole class if only one value is required?– ramaral
I understand that it makes no sense to pass objects that own resources like streams and network connections, but in cases like the stopwatch that has these methods there that you quoted, I see no harm. Maybe I’m not seeing beyond this example, so I asked for a reference to this principle. With other examples maybe I understand better.
– Pablo Almeida
Of course, in a simple example like this, it is of little importance. Suppose that the Activity represents a car race, besides the stopwatch would have to pass the list of cars. Both Chronometer as Car would have to implement Parcelable. What I say is that it’s best to just pass the race state. A class that implements Parcelable and representing that state, eg: chronometer value and position of cars. Think of other situations where there may be a larger number of classes involved. Regarding a reference: I do not know if it exists.
– ramaral
Right. I think I understand the advice. I’ll keep that in mind. Thank you for the clarification. :)
– Pablo Almeida