2

I have been trying for a few days now to correctly implement the onSaveInstanceState() method, but with no success up until now.

What am I doing wrong? My code does not return an error, but the state of the checkboxes is not saved?

Is it ok to implement the onSaveInstanceState() method?

Would it be better if I used SharedPreferences?

What I want is not to lose the checkbox selection on rotating the screen. If anyone can correct what I am doing I would be grateful!

Here is what I have:

MainActivity.java:

package com.example.alex.savepreferencescheckbox;

import android.annotation.SuppressLint;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    AlertDialog dialog;
    CheckBox cbAllDay, cbBefore12, cbBetween1216, cbBetween1620, ccbAfter20;
    Boolean myBoolean1, myBoolean2, myBoolean3, myBoolean4, myBoolean5;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    public void alertDialog(View view) {

        if (dialog == null) {

            AlertDialog.Builder builder;
            builder = new AlertDialog.Builder(this);
            LayoutInflater inflater = this.getLayoutInflater();
            @SuppressLint("InflateParams") View checkBoxView = inflater.inflate(R.layout.markers_filtering, null);
            builder.setView(checkBoxView);
            cbAllDay = (CheckBox) checkBoxView.findViewById(R.id.checkBox1);
            cbBefore12 = (CheckBox) checkBoxView.findViewById(R.id.checkBox2);
            cbBetween1216 = (CheckBox) checkBoxView.findViewById(R.id.checkBox3);
            cbBetween1620 = (CheckBox) checkBoxView.findViewById(R.id.checkBox4);
            ccbAfter20 = (CheckBox) checkBoxView.findViewById(R.id.checkBox5);


            dialog = builder.create();

        }
        dialog.show();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean("CheckBox1", cbAllDay.isChecked());
        outState.putBoolean("CheckBox2", cbBefore12.isChecked());
        outState.putBoolean("CheckBox3", cbBetween1216.isChecked());
        outState.putBoolean("CheckBox4", cbBetween1620.isChecked());
        outState.putBoolean("CheckBox5", ccbAfter20.isChecked());

    }


    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        myBoolean1 = savedInstanceState.getBoolean("CheckBox1");
        myBoolean2 = savedInstanceState.getBoolean("CheckBox2");
        myBoolean3 = savedInstanceState.getBoolean("CheckBox3");
        myBoolean4 = savedInstanceState.getBoolean("CheckBox4");
        myBoolean5 = savedInstanceState.getBoolean("CheckBox5");
    }

    public void applyFilter(View view) {

        dialog.dismiss();

        if (cbAllDay.isChecked()){
            Toast.makeText(this, "The first box was checked", Toast.LENGTH_SHORT).show();

        } else if (cbBefore12.isChecked()){
            Toast.makeText(this, "The second box was checked", Toast.LENGTH_SHORT).show();

        } else if (cbBetween1216.isChecked()){
            Toast.makeText(this, "The third box was checked", Toast.LENGTH_SHORT).show();

        } else if (cbBetween1620.isChecked()){
            Toast.makeText(this, "The forth box was checked", Toast.LENGTH_SHORT).show();

        } else if (ccbAfter20.isChecked()){
            Toast.makeText(this, "The fifth box was checked", Toast.LENGTH_SHORT).show();

        }
    }

    public void doNothing(View view) {

        dialog.dismiss();
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.alex.savepreferencescheckbox.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:id="@+id/textView" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Button"
        android:id="@+id/button"
        android:layout_marginTop="71dp"
        android:layout_below="@+id/textView"
        android:layout_alignParentStart="true"
        android:onClick="alertDialog"/>
</RelativeLayout>

markers_filtering.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Choose Your Hour!"
        android:textSize="25sp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="10dp"
        android:layout_gravity="center"
        android:id="@+id/title_hour_selection"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <CheckBox
        android:id="@+id/checkBox1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/title_hour_selection"
        android:layout_marginLeft="30dp"
        android:layout_marginStart="30dp"
        android:text="All day long" />

    <CheckBox
        android:id="@+id/checkBox2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp"
        android:layout_marginStart="30dp"
        android:text="Before 12 P.M."
        android:layout_below="@+id/checkBox1"/>

    <CheckBox
        android:id="@+id/checkBox3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/checkBox2"
        android:layout_marginLeft="30dp"
        android:layout_marginStart="30dp"
        android:text="Between 12.00 P.M. - 16.00 P.M." />

    <CheckBox
        android:id="@+id/checkBox4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/checkBox3"
        android:layout_marginLeft="30dp"
        android:layout_marginStart="30dp"
        android:text="Between 16.00 P.M. - 20.00 P.M." />

    <CheckBox
        android:id="@+id/checkBox5"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp"
        android:layout_marginStart="30dp"
        android:layout_below="@+id/checkBox4"
        android:text="After 20.00 P.M."
        android:layout_marginBottom="10dp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="OK"
        android:layout_marginLeft="30dp"
        android:layout_marginStart="30dp"
        android:layout_marginBottom="30dp"
        android:layout_below="@+id/checkBox5"
        android:id="@+id/okButton"
        android:onClick="applyFilter"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cancel"
        android:id="@+id/cancelButton"
        android:layout_below="@+id/checkBox5"
        android:layout_alignRight="@+id/checkBox5"
        android:layout_alignEnd="@+id/checkBox5"
        android:layout_marginRight="30dp"
        android:layout_marginEnd="30dp"
        android:layout_marginBottom="30dp"
        android:onClick="doNothing"/>


</RelativeLayout>
Bono
  • 4,757
  • 6
  • 48
  • 77
Alex Simion
  • 93
  • 1
  • 14
  • If you're still having problems consider using [DialogFragment](http://developer.android.com/guide/topics/ui/dialogs.html): "Using DialogFragment to manage the dialog ensures that it correctly handles lifecycle events such as when the user presses the Back button or rotates the screen". Precisely what you're looking for. – Bö macht Blau Apr 26 '16 at 05:52

3 Answers3

1

New Edit:

I made a similar project like yours and tested it. Your code looks fine but only thing you forgot is to set up your checkboxes in alertDialog() method with the saved values provided by onRestoreInstanceState() method.

Here is the full code of MainActivity.java:

package com.example.alex.savepreferencescheckbox;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    AlertDialog dialog;
    CheckBox cbAllDay, cbBefore12, cbBetween1216, cbBetween1620, ccbAfter20;
    Boolean myBoolean1, myBoolean2, myBoolean3, myBoolean4, myBoolean5;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void alertDialog(View view) {

        if (dialog == null) {

            AlertDialog.Builder builder;
            builder = new AlertDialog.Builder(this);
            LayoutInflater inflater = this.getLayoutInflater();
            @SuppressLint("InflateParams") View checkBoxView = inflater.inflate(R.layout.markers_filtering, null);
            builder.setView(checkBoxView);

            cbAllDay = (CheckBox) checkBoxView.findViewById(R.id.checkBox1);
            if (myBoolean1 != null) {
                cbAllDay.setChecked(myBoolean1);
            }
            cbBefore12 = (CheckBox) checkBoxView.findViewById(R.id.checkBox2);
            if (myBoolean2 != null) {
                cbBefore12.setChecked(myBoolean2);
            }

            cbBetween1216 = (CheckBox) checkBoxView.findViewById(R.id.checkBox3);
            if (myBoolean3 != null) {
                cbBetween1216.setChecked(myBoolean3);
            }

            cbBetween1620 = (CheckBox) checkBoxView.findViewById(R.id.checkBox4);
            if (myBoolean4 != null) {
                cbBetween1620.setChecked(myBoolean4);
            }

            ccbAfter20 = (CheckBox) checkBoxView.findViewById(R.id.checkBox5);
            if (myBoolean5 != null) {
                ccbAfter20.setChecked(myBoolean5);
            }

            dialog = builder.create();
        }
        dialog.show();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean("CheckBox1", cbAllDay.isChecked());
        outState.putBoolean("CheckBox2", cbBefore12.isChecked());
        outState.putBoolean("CheckBox3", cbBetween1216.isChecked());
        outState.putBoolean("CheckBox4", cbBetween1620.isChecked());
        outState.putBoolean("CheckBox5", ccbAfter20.isChecked());
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        myBoolean1 = savedInstanceState.getBoolean("CheckBox1");
        myBoolean2 = savedInstanceState.getBoolean("CheckBox2");
        myBoolean3 = savedInstanceState.getBoolean("CheckBox3");
        myBoolean4 = savedInstanceState.getBoolean("CheckBox4");
        myBoolean5 = savedInstanceState.getBoolean("CheckBox5");
    }

    public void applyFilter(View view) {

        dialog.dismiss();

        if (cbAllDay.isChecked()) {
            Toast.makeText(this, "The first box was checked", Toast.LENGTH_SHORT).show();
        } else if (cbBefore12.isChecked()) {
            Toast.makeText(this, "The second box was checked", Toast.LENGTH_SHORT).show();
        } else if (cbBetween1216.isChecked()) {
            Toast.makeText(this, "The third box was checked", Toast.LENGTH_SHORT).show();
        } else if (cbBetween1620.isChecked()) {
            Toast.makeText(this, "The forth box was checked", Toast.LENGTH_SHORT).show();
        } else if (ccbAfter20.isChecked()) {
            Toast.makeText(this, "The fifth box was checked", Toast.LENGTH_SHORT).show();
        }
    }

    public void doNothing(View view) {

        dialog.dismiss();
    }
}

and here are the screenshots of the emulator (Galaxy Nexus API 23, it works with the API 16 too, I've tested it):

Portrait mode:

Galaxy Nexus Api 23 Portrait mode

Landscape mode:

Galaxy Nexus Api 23 Landscape mode

Andritchi Alexei
  • 1,380
  • 1
  • 16
  • 23
  • If I add this in the oncreate it will give me NPE. – Alex Simion Apr 25 '16 at 17:09
  • Initialize your checkboxes in `onCreate()` method. I made an edit of the answer. Hope this will help you. – Andritchi Alexei Apr 25 '16 at 17:51
  • I cannot save them like you suggest here. as checkBoxView in the view from the alert dialog. I can initialize them like this cbAllDay = (CheckBox)findViewById(R.id.checkBox1); but even like that I get Attempt to invoke virtual method 'void android.widget.CheckBox.setChecked(boolean)' on a null object reference – Alex Simion Apr 25 '16 at 18:28
  • You have to check if `savedInstanceState` is not null. That's why you've got NPE. – Andritchi Alexei Apr 25 '16 at 19:15
  • Can you give me an example please? – Alex Simion Apr 25 '16 at 19:16
  • I edited my answer. As an example you can look at [link](http://stackoverflow.com/questions/6525698/how-to-use-onsavedinstancestate-example-please) – Andritchi Alexei Apr 25 '16 at 19:17
  • Hello! I've been away for a few days but now I m back on this, as it is still not working. After analyzing a little I think that I get the NPE because even though I am saving the checkbox state I am saving it for the alert dialog and when the activity is recreated it tries to get the values for the checkboxes but it can't do it, because even if I initialize the checkboxes in on create it will search on on create and it will not find any checkbox as on create is for the R.layout.activity_main and the checkboxes are in the R.layout.markers_filtering. What do you think? Is this right? – Alex Simion Apr 29 '16 at 10:13
  • Hello, I don't know if you figured it out your problem already, anyway **I've made an edit of the answer**. On my machine, the app is working fine. – Andritchi Alexei Apr 30 '16 at 13:52
  • You're a life saver! Thanks a lot! It works now. I have to do some other adjustments as this was only an example code but important is that I understand what it was wrong. So simple and yet so many headaches:-) By any chance you speak Romanian(being from Moldova)? – Alex Simion Apr 30 '16 at 17:45
  • Yes I'm from Moldova of Republic and I'm glad I helped a brother (We're the same of despite of political conjecture of my country ). I'm really glad I helped you with your issue. I know this is not allowed but..."Paste fericit frate". I hope my message will not be banned. Enjoy android development. It is a great API and a great community. And that's why I love stackoverflow community (maybe it is some times too rude but it gave you the best answers or at least the best chosen answers** – Andritchi Alexei Apr 30 '16 at 19:24
  • Thanks once again and "Paste fericit si tie!:-)" – Alex Simion Apr 30 '16 at 19:29
  • I'm sorry if I added in a way the religious thing (with "paste fericit" and so on...). Anyway, happy codding :) – Andritchi Alexei Apr 30 '16 at 19:39
0

Add this line in your manifest.xml where u declare activity it prevent to recreate view when screen will be rotating

android:configChanges="keyboardHidden|orientation"

Naitik
  • 101
  • 6
  • 2
    This is not a solution this is only a way of avoiding it. I would like to have the possibility to rotate the screen, to open another app evetually and to resume the status of the app from where I left it – Alex Simion Apr 25 '16 at 17:12
  • If u want to resume the app from where user left and you want to store last data till use come next time. Then use sharedprefence for store it – Naitik Apr 25 '16 at 17:15
0

It looks in your code that you are retrieving what the checkbox status was, but you aren't doing anything with it other than setting the variables to it:

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    myBoolean1 = savedInstanceState.getBoolean("CheckBox1");
    myBoolean2 = savedInstanceState.getBoolean("CheckBox2");
    myBoolean3 = savedInstanceState.getBoolean("CheckBox3");
    myBoolean4 = savedInstanceState.getBoolean("CheckBox4");
    myBoolean5 = savedInstanceState.getBoolean("CheckBox5");
}

What you would need to do is set the checkbox to what each of those booleans were:

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    myBoolean1 = savedInstanceState.getBoolean("CheckBox1");
    cbAllDay.setChecked(myBoolean1);
    // ...Continue with implementation here.
}
Alexander N.
  • 1,458
  • 14
  • 25
  • Did what you suggested and when I rotate now the app crashes with java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.CheckBox.setChecked(boolean)' on a null object reference – Alex Simion Apr 25 '16 at 17:09
  • I see what you did there. Move the `cbAllDay.setChecked(myBoolean1);` to the alert dialogue. You need to have set the instance of the object before you can assign the object. – Alexander N. Apr 25 '16 at 18:15
  • I agree with what was commented above. If you initialize your checkboxes in the oncreate method, this strategy listed in my answer should work. – Alexander N. Apr 25 '16 at 18:18
  • Well I did it and it does not work. No matter where I put it in the dialog the app will crash as it cannot execute the on click method to start the alert dialog java.lang.IllegalStateException: Could not execute method for android:onClick – Alex Simion Apr 25 '16 at 18:38