2

I'm attempting to save and restore a boolean field when the screen orientation changes. For whatever reason the field is saving/restoring correctly during the first orientation change, but when the orientation changes back to the initial state, the value of the boolean is wrong when onSaveInstanceState() is called.

According to this answer, I added android:configChanges="orientation" to the corresponding activity tag in the manifest. The following code contains the relevant methods, simplified for clarity:

public class SignatureActivity extends AppCompactActivity {
    private boolean signaturePadIsEmpty = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String orientation = getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT ? "portrait" : "landscape";
        Log.d(TAG, "onCreate: Orientation is " + orientation + ", signaturePadIsEmpty = " + signaturePadIsEmpty);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        signaturePadIsEmpty = savedInstanceState.getBoolean("SignaturePadIsEmpty");

        String orientation = getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT ? "portrait" : "landscape";
        Log.d(TAG, "onRestoreInstanceState: Orientation is " + orientation + ", signaturePadIsEmpty = " + signaturePadIsEmpty);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean("SignaturePadIsEmpty", signaturePadIsEmpty);

        String orientation = getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT ? "portrait" : "landscape";
        Log.d(TAG, "onSaveInstanceState: Orientation is " + orientation + ", signaturePadIsEmpty = " + signaturePadIsEmpty);
    }
}

Here's the Logcat output when I start the activity and change from portrait -> landscape and then from landscape -> portrait:

06-27 11:50:08.037 32656-32656/com.example.www.debug D/SignatureActivity: onCreate: Orientation is portrait, signaturePadIsEmpty = true
06-27 11:50:12.405 32656-32656/com.example.www.debug D/SignatureActivity: onSaveInstanceState: Orientation is landscape, signaturePadIsEmpty = false
06-27 11:50:12.461 32656-32656/com.example.www.debug D/SignatureActivity: onCreate: Orientation is landscape, signaturePadIsEmpty = true
06-27 11:50:12.465 32656-32656/com.example.www.debug D/SignatureActivity: onRestoreInstanceState: Orientation is landscape, signaturePadIsEmpty = false
06-27 11:50:15.068 32656-32656/com.example.www.debug D/SignatureActivity: onSaveInstanceState: Orientation is portrait, signaturePadIsEmpty = true
06-27 11:50:15.131 32656-32656/com.example.www.debug D/SignatureActivity: onCreate: Orientation is portrait, signaturePadIsEmpty = true
06-27 11:50:15.133 32656-32656/com.example.www.debug D/SignatureActivity: onRestoreInstanceState: Orientation is portrait, signaturePadIsEmpty = true

Edit: The problem turned out to be caused by my implementation of the signature pad's event handlers:

private void initializeLayoutElements(final int orientation) {
    signaturePad = findViewById(R.id.signature_pad);
    signaturePad.setOnSignedListener(new SignaturePad.OnSignedListener() {
        @Override
        public void onStartSigning() {
            signaturePadIsEmpty = false;
        }

        @Override
        public void onSigned() {
        }

        @Override
        public void onClear() {
            signaturePadIsEmpty = true;
        }
    });
}

The onClear() method was being called after onRestoreInstanceState() and was setting the flag to true. Since the solution posted by @SOreadytohelp answered my original question, I'm accepting their answer.

Alex
  • 139
  • 9

1 Answers1

1

I've created a simple demo here on Github to show you how to store and restore instance state, let me know if you understand it. It's a simple app that has a button and when you press the button you change the state of the boolean, and if you rotate the screen you still have the same value as before. I hope is what you are looking for.

They key is in onRestoreInstanceState() get the Boolean and in onSaveInstanceState() save the Boolean and you don't need this android:configChanges="orientation in the manifest.xml

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    signaturePadIsEmpty = savedInstanceState.getBoolean("SignaturePadIsEmpty");
    tvState.setText(String.valueOf(signaturePadIsEmpty));

}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean("SignaturePadIsEmpty", signaturePadIsEmpty);
}
Skizo-ozᴉʞS ツ
  • 19,464
  • 18
  • 81
  • 148
  • Thanks for your answer. The relevant lines of code in your snippet are identical to the snippet in my question, so I'm not sure what I should be doing differently. – Alex Jun 27 '19 at 17:38
  • I mean, if you don't add the thing of your `manifest.xml` on my demo it works perfect, even if I copy your code... – Skizo-ozᴉʞS ツ Jun 27 '19 at 18:06
  • I found the issue. Looks like the signature pad's `onClear()` event handler was being called after restoring the state. I set the flag `signaturePadIsEmpty` to `true` in this handler. – Alex Jun 27 '19 at 18:11
  • 1
    Sorry, should have included that part of the code. I assumed the bug was related to how I was saving/restoring the instance state. – Alex Jun 27 '19 at 18:42