How do I avoid resetting screen elements when turning the phone?

3

I have an Activity with only a stopwatch basically, and when the phone turns, the stopwatch is reset.

Is there an event that causes Activity to be restarted while doing this? I would like to prevent this behavior.

    
asked by anonymous 09.03.2016 / 02:24

2 answers

5

The problem

When you change the device orientation, Android will destroy and re-create Activity . What is happening is that you are probably starting your timer at onCreate . As onCreate is being recalled, the status its 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 developer settings the device)

I imagine your code looks 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

}    

You may not have a Timer class but other simpler variables to compose the timer state, but the principle is the same.

Solution

You should override the onSaveInstanceState method of Activity , which is called when Activity is destroyed by the system. The system sends this method a Bundle , called here estadoDeSaida , within which you will place the data you want to persist between screen restarts. As you may already know, a Bundle accepts data from Java primitives, String s, Serializable objects, and Parcelable objects (among some 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 re-creation, the onCreate will be called, and will be passed that same Bundle in the savedInstanceState parameter, instead of null that is there when the Activity is starting normally. From it, you have to remove the data you have placed and re-create your timer.

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();
}

In this way, your Activity is protected from the loss of this information and your timer will not reset.

However, in the specific case of the timer, you may need a more ingenious solution to avoid the loss of seconds in which the timer would freeze, waiting for destruction and re-creation. This solution is for the simplest (and most common) case in which this is not important.

    
09.03.2016 / 06:22
1

Great solution Pablo Almeida, I used this same, with a Serializable object, so I did not have to implement anything of the 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();
}
    
01.07.2018 / 12:30