【问题标题】:onSaveInstanceState or SharedPreferences for multiple CheckBoxes?多个复选框的 onSaveInstanceState 或 SharedPreferences?
【发布时间】:2016-08-19 03:10:39
【问题描述】:

我已经尝试了几天来正确实现onSaveInstanceState() 方法,但到目前为止还没有成功。

我做错了什么?我的代码没有返回错误,但是复选框的状态没有保存?

可以实现onSaveInstanceState()方法吗?

如果我使用SharedPreferences会更好吗?

我想要的是不要在旋转屏幕时丢失复选框选择。如果有人能纠正我正在做的事情,我将不胜感激!

这是我所拥有的:

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>

ma​​rkers_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>

【问题讨论】:

  • 如果您仍然遇到问题,请考虑使用DialogFragment:“使用 DialogFragment 管理对话框可确保它正确处理生命周期事件,例如用户按下后退按钮或旋转屏幕时”。正是您要寻找的。​​span>

标签: android checkbox sharedpreferences savestate


【解决方案1】:

在您的 manifest.xml 中添加这一行,您可以在其中声明当屏幕旋转时阻止重新创建视图的活动

android:configChanges="keyboardHidden|orientation"

【讨论】:

  • 这不是一个解决方案,这只是一种避免它的方法。我希望有可能旋转屏幕,最终打开另一个应用程序并从我离开的地方恢复应用程序的状态
  • 如果你想从用户离开的地方恢复应用,并且你想存储最后的数据直到下次使用。然后使用 sharedprefence 存储它
【解决方案2】:

它在您的代码中查看您正在检索复选框的状态,但除了为其设置变量之外,您没有对其进行任何操作:

@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");
}

您需要做的是将复选框设置为每个布尔值:

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    myBoolean1 = savedInstanceState.getBoolean("CheckBox1");
    cbAllDay.setChecked(myBoolean1);
    // ...Continue with implementation here.
}

【讨论】:

  • 按照您的建议做了,当我现在旋转时,应用程序因 java.lang.NullPointerException 崩溃:尝试在空对象引用上调用虚拟方法 'void android.widget.CheckBox.setChecked(boolean)'
  • 我知道你在那里做了什么。将cbAllDay.setChecked(myBoolean1); 移至警报对话框。您需要先设置对象的实例,然后才能分配对象。
  • 我同意上面的评论。如果您在 oncreate 方法中初始化您的复选框,我的答案中列出的这个策略应该可以工作。
  • 好吧,我做到了,但它不起作用。无论我将它放在对话框中的哪个位置,应用程序都会崩溃,因为它无法执行单击方法来启动警报对话框 java.lang.IllegalStateException: Could not execute method for android:onClick
【解决方案3】:

新编辑:

我做了一个与您类似的项目并对其进行了测试。您的代码看起来不错,但您唯一忘记的是在alertDialog() 方法中设置您的复选框,并使用onRestoreInstanceState() 方法提供的保存值。

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

这是模拟器的截图(Galaxy Nexus API 23,它也适用于 API 16,我已经测试过了):

人像模式:

横向模式:

【讨论】:

  • 如果我在 oncreate 中添加它,它会给我 NPE。
  • onCreate() 方法中初始化你的复选框。我对答案进行了编辑。希望这会对你有所帮助。
  • 我不能像你在这里建议的那样保存它们。在警报对话框的视图中作为 checkBoxView。我可以像这样初始化它们 cbAllDay = (CheckBox)findViewById(R.id.checkBox1);但即使这样,我也会尝试在空对象引用上调用虚拟方法 'void android.widget.CheckBox.setChecked(boolean)'
  • 您必须检查savedInstanceState 是否不为空。这就是你有 NPE 的原因。
  • 你能给我举个例子吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-13
  • 2018-08-24
相关资源
最近更新 更多