简体   繁体   English

SharedPreferences字符串设置应用程序终止后丢失的数据(Android模拟器)

[英]SharedPreferences String Set data lost after app kill (android emulator)

I am running this on an emulator: 5554:Nexus_5_API_22_x86. 我正在模拟器上运行它:5554:Nexus_5_API_22_x86。

I am trying to learn SharedPreferences and have written a simple test program. 我正在尝试学习SharedPreferences并编写了一个简单的测试程序。

It contains two buttons: one adds a String + random # to a set which will be stored in SharedPreferences, and the other prints the contents of that set. 它包含两个按钮:一个按钮将String + random#添加到将存储在SharedPreferences中的集合,另一个按钮将显示该集合的内容。

Whenever I press the square button on the bottom right hand of the screen and press 'x' to close the app window, then relaunch the app, the contents of the set are reset - in other words, printing the set yields nothing. 每当我按下屏幕右下角的方形按钮并按“ x”关闭应用程序窗口,然后重新启动应用程序时,设备集的内容都会重置-换句话说,打印设备不会产生任何效果。

However, if I exit the app using only the back button, the contents remain - in other words, printing the set yields whatever was in it before. 但是,如果我仅使用“后退”按钮退出应用程序,内容将保留-换句话说,打印设置将产生以前的内容。

Java: Java:

...

public class MainActivity extends AppCompatActivity
{
    final int PREF_MODE_PRIVATE = 0;
    TextView output;
    Set<String> testSet;
    Random randomGenerator = new Random();
    SharedPreferences data;
    SharedPreferences.Editor dataEditor;

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

        output = (TextView) findViewById(R.id.textView); //getting the output textfield
        data = getPreferences(PREF_MODE_PRIVATE);

        //If first-time setup has not been completed, execute the following block
        //I don't want the String Set to be reset to empty every time the app is launched
        if(data.getBoolean("initialized", false) == false)
        {
            //Adding the empty set to storage
            testSet = new HashSet<String>();

            dataEditor = data.edit();
            dataEditor.putStringSet("testSet", testSet); //Add the empty Set to storage
            dataEditor.putBoolean("initialized", true); //Set initialized flag to true
            dataEditor.apply();
        }
    }

    public void printTestSet(View view)
    {
        output.setText(""); //Clears the text field
        Set<String> toBePrinted = data.getStringSet("testSet", null); //Gets the String Set

        //Prints content of the String Set
        if(toBePrinted != null)
        {
            for(String word : toBePrinted)
            {
                output.append(word + '\n');
            }
        }
    }

    public void addToTestSet(View view)
    {
        //Generate a string followed by a random number and add it to the String Set
        int randomInt = randomGenerator.nextInt(1000);
        data.getStringSet("testSet", null).add("NEW STRING #" + randomInt);
    }
}

The button that prints the String Set calls printTestSet and the one that adds a String to the Set calls addToTestSet . 打印字符串集的按钮调用printTestSet ,将字符串添加到集合的addToTestSet调用addToTestSet

Upon creation, the app uses a simple boolean to check if it has been initialized the for the first time. 创建后,该应用将使用一个简单的布尔值来检查它是否已首次初始化。 If not, it adds an empty String Set to storage and sets the boolean to true. 如果没有,它将向存储添加一个空的String Set并将布尔值设置为true。 If the boolean is already true (meaning it has already added the empty string set), that step is skipped. 如果布尔值已经为真(意味着它已经添加了空字符串集),那么将跳过该步骤。

It looks like you're not saving the shared preferences in addToTestSet. 似乎您没有将共享的首选项保存在addToTestSet中。 When you do getStringSet and then add, you need to again save the string Set back into shared prefs like you do in your onCreate() using dataEditor.apply() . 在执行getStringSet然后添加时,您需要像使用dataEditor.apply()onCreate()一样,将字符串Set重新保存回共享首dataEditor.apply()

Or if you want to be a bit more efficient, you can save your stringSet in the activity's onPause() method to prevent constantly writing to SharedPrefs 或者,如果您想提高效率,可以将stringSet保存在活动的onPause()方法中,以防止不断写入SharedPrefs

When you hit back, your app process isn't being killed, which means when you open it up again the Android system is restoring whatever it can (what was written in textViews , checkboxes that were checked, etc. simple things like that). 当您回击时,您的应用程序进程不会被杀死,这意味着当您再次打开它时,Android系统将还原它所能进行的一切(在textViews中编写的内容,已选中的checkboxes等类似的简单内容)。 What you see in the box might not actually be getting populated by SharedPrefs . 您在框中看到的内容可能实际上未由SharedPrefs填充。

You need to either commit your data either realtime (where you are doing apply) or in application life cycle handler onpause (when your app goes to background). 您需要实时(在执行应用的位置)或在应用程序生命周期处理程序中暂停提交数据(当您的应用程序进入后台时)。 Use option 1 when you have little data or 2 when you have large amount of data to commit. 当数据很少时,请使用选项1;在要提交大量数据时,请使用选项2。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM