Android "firstUse" 之后 onCreate 报告的首选项设置不一致——我的错,但怎么办?
Android Preferences settings not consistently reported by onCreate after "firstUse"--my fault, but how?
EDIT 我忘记了一大堆代码。插入就在这里。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.w("Before switch", (String) item.getTitle());
switch (item.getItemId()) {
case R.id.menu_settings:
Log.w("Before intent","\n");
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
Log.w("back from intent", "\n");
preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
focusAtClue = preferences.getBoolean("focus",true);
screenSaver = preferences.getBoolean("screen",true);
Log.w("after intent", focusAtClue + " " + screenSaver);
return true;
default:
Log.w("onOptItemSel","default");
return super.onOptionsItemSelected(item);
}
}
}
此处的 onCreate
代码用于创建首选项,如图所示。 preferences.xml
中的 xml
作为注释插入。它也包含在下面,完好无损。
首选项存储在键 focus
和 screen
下。对吗?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
boolean firstUse = preferences.getBoolean(FIRST_USE, true);
if (firstUse){
Toast helloMessage = Toast.makeText(getApplicationContext(), "Hello First Time User",Toast.LENGTH_LONG);
helloMessage.show();
editor = preferences.edit();
editor.putBoolean(FIRST_USE, false);
editor.putBoolean ("focus", false);
/*NOTE THE MATCHED STRING vvvvv
<CheckBoxPreference
android:key="focus" android:title="@string/focusAfterShow" android:summary="Always place the cursor" android:defaultValue="false"/> */
editor.putBoolean ("screen", false);
/*NOTE THE MATCHED STRING vvvvvv
<CheckBoxPreference
android:key="screen" android:title="@string/screenSaver" android:summary="Keep screen on" android:defaultValue="false" /> */
editor.commit();
}
else {
///////////////////// problems here *******************
SharedPreferences preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
focusAtClue = preferences.getBoolean("focus",focusAtClue);
screenSaver = preferences.getBoolean("screen",screenSaver);
Log.w("oncreate:", focusAtClue + " " + screenSaver);
///////////////////// problems
}
}
preferences.xml
:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Screen options">
>
<CheckBoxPreference
android:key="focus"
android:title="@string/focusAfterShow"
android:summary="Always place the cursor at the 'clue' (sum) after tapping 'Show'."
android:defaultValue="false"
/>
<CheckBoxPreference
android:key="screen"
android:title="@string/screenSaver"
android:summary="Keep screen on at all times while running this app."
android:defaultValue="false"
/>
</PreferenceCategory>
</PreferenceScreen>
离开主屏幕然后返回主屏幕后,偏好没有变化,如logcat
.
所示
然后我通过选中它的框来更改第一个首选项。 logcat
显示正确。涉及的代码在SettingsFragment.java
:
package com.bffmedia.hour11app;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.util.Log;
public class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
@Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
//SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
Log.w("onSharedPrefChgd", sharedPreferences.getBoolean("focus",false) + " " + sharedPreferences.getBoolean("screen",false));
}
}
然后我从内存中的应用程序列表中删除该应用程序,然后 运行 从应用程序图标中删除它。
onCreate
表示两个值都是 FALSE,但只有第一个是。
这里的 logcat
只有我通过 Log.w
写的行。有 3 个组要看:创建首选项和更改第一个首选项,效果很好。然后是第二个 onCreate
,其中两个值据说都是 false
,这是错误的——第一个是真实的——,但设置屏幕显示我确实选中了第一个框.
我对自己做错了什么一无所知。
05-16 13:25:20.290 18778-18778/com.bffmedia.hour11app W/Before switch? Settings
05-16 13:25:20.291 18778-18778/com.bffmedia.hour11app W/Before intent? [
05-16 13:25:20.292 438:0x1a07 I/ActivityManager ]
START u0 {cmp=com.bffmedia.hour11app/.SettingsActivity} from pid 18778
05-16 13:25:20.449 18778-18778/com.bffmedia.hour11app W/back from intent?
05-16 13:25:20.450 18778:0x495a W/after intent ]
false false ***************************** CORRECT ************************
05-16 13:35:16.717 18778-18778/com.bffmedia.hour11app W/onSharedPrefChgd?
true false *********************************** CORRECT
05-16 13:37:21.185 20014-20014/com.bffmedia.hour11app W/Before switch? Settings
05-16 13:37:21.186 20014-20014/com.bffmedia.hour11app W/Before intent? [
05-16 13:37:21.188 438:0x2ef I/ActivityManager ]
START u0 {cmp=com.bffmedia.hour11app/.SettingsActivity} from pid 20014
05-16 13:37:21.245 20014-20014/com.bffmedia.hour11app W/back from intent? [
05-16 13:37:21.245 20014:0x4e2e W/after intent ]
false false *************************************** WHY? *******************************************
这里的问题是您没有查看正确的首选项 xml 文件。来自 PreferenceFragment
的首选项被保存到默认首选项 xml 文件中,并且在您的 MainActivity 中,因为您正在使用 getSharedPreferences(SETTINGS, MODE_PRIVATE)
,另外创建一个新文件到默认首选项 xml 文件。
为了修复它,只需将该代码更改为 PreferenceManager.getDefaultSharedPreferences(this)
,然后您将在 PreferenceFragment
使用的相同首选项 xml 文件中查找。
更多信息here.... and also here.....
这就是您需要做的全部修复工作,我刚刚测试了它,它可以工作!
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
//use this instead:
preferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean firstUse = preferences.getBoolean(FIRST_USE, true);
if (firstUse){
Toast helloMessage = Toast.makeText(getApplicationContext(), "Hello First Time User",Toast.LENGTH_LONG);
helloMessage.show();
editor = preferences.edit();
editor.putBoolean(FIRST_USE, false);
editor.putBoolean ("focus", false);
/*NOTE THE MATCHED STRING vvvvv
<CheckBoxPreference
android:key="focus" android:title="@string/focusAfterShow" android:summary="Always place the cursor" android:defaultValue="false"/> */
editor.putBoolean ("screen", false);
/*NOTE THE MATCHED STRING vvvvvv
<CheckBoxPreference
android:key="screen" android:title="@string/screenSaver" android:summary="Keep screen on" android:defaultValue="false" /> */
editor.commit();
}
else {
///////////////////// problems here *******************
//no need to create another preferences, it's already defined above
//SharedPreferences preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
//This should work now!!!!!!
focusAtClue = preferences.getBoolean("focus",focusAtClue);
screenSaver = preferences.getBoolean("screen",screenSaver);
Log.w("oncreate:", focusAtClue + " " + screenSaver);
Toast helloMessage = Toast.makeText(getApplicationContext(), "Hello Returning User " + focusAtClue + " " + screenSaver,Toast.LENGTH_LONG);
helloMessage.show();
///////////////////// problems
}
}
还有一点需要注意,下面这段代码看起来不会像您想象的那样运行。这段代码的执行不会在调用 startActivity()
时暂停,它会继续执行。因此,您在此处的日志将反映 SharedPreference 在设置 Activity 打开之前的状态,而不是之后。
此外,您也应该在此处使用默认的共享首选项。
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
Log.w("back from intent", "\n");
//preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
preferences = PreferenceManager.getDefaultSharedPreferences(this);
focusAtClue = preferences.getBoolean("focus",true);
screenSaver = preferences.getBoolean("screen",true);
Log.w("after intent", focusAtClue + " " + screenSaver);
return true;
EDIT 我忘记了一大堆代码。插入就在这里。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.w("Before switch", (String) item.getTitle());
switch (item.getItemId()) {
case R.id.menu_settings:
Log.w("Before intent","\n");
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
Log.w("back from intent", "\n");
preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
focusAtClue = preferences.getBoolean("focus",true);
screenSaver = preferences.getBoolean("screen",true);
Log.w("after intent", focusAtClue + " " + screenSaver);
return true;
default:
Log.w("onOptItemSel","default");
return super.onOptionsItemSelected(item);
}
}
}
此处的 onCreate
代码用于创建首选项,如图所示。 preferences.xml
中的 xml
作为注释插入。它也包含在下面,完好无损。
首选项存储在键 focus
和 screen
下。对吗?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
boolean firstUse = preferences.getBoolean(FIRST_USE, true);
if (firstUse){
Toast helloMessage = Toast.makeText(getApplicationContext(), "Hello First Time User",Toast.LENGTH_LONG);
helloMessage.show();
editor = preferences.edit();
editor.putBoolean(FIRST_USE, false);
editor.putBoolean ("focus", false);
/*NOTE THE MATCHED STRING vvvvv
<CheckBoxPreference
android:key="focus" android:title="@string/focusAfterShow" android:summary="Always place the cursor" android:defaultValue="false"/> */
editor.putBoolean ("screen", false);
/*NOTE THE MATCHED STRING vvvvvv
<CheckBoxPreference
android:key="screen" android:title="@string/screenSaver" android:summary="Keep screen on" android:defaultValue="false" /> */
editor.commit();
}
else {
///////////////////// problems here *******************
SharedPreferences preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
focusAtClue = preferences.getBoolean("focus",focusAtClue);
screenSaver = preferences.getBoolean("screen",screenSaver);
Log.w("oncreate:", focusAtClue + " " + screenSaver);
///////////////////// problems
}
}
preferences.xml
:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Screen options">
>
<CheckBoxPreference
android:key="focus"
android:title="@string/focusAfterShow"
android:summary="Always place the cursor at the 'clue' (sum) after tapping 'Show'."
android:defaultValue="false"
/>
<CheckBoxPreference
android:key="screen"
android:title="@string/screenSaver"
android:summary="Keep screen on at all times while running this app."
android:defaultValue="false"
/>
</PreferenceCategory>
</PreferenceScreen>
离开主屏幕然后返回主屏幕后,偏好没有变化,如logcat
.
然后我通过选中它的框来更改第一个首选项。 logcat
显示正确。涉及的代码在SettingsFragment.java
:
package com.bffmedia.hour11app;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.util.Log;
public class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
@Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
//SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
Log.w("onSharedPrefChgd", sharedPreferences.getBoolean("focus",false) + " " + sharedPreferences.getBoolean("screen",false));
}
}
然后我从内存中的应用程序列表中删除该应用程序,然后 运行 从应用程序图标中删除它。
onCreate
表示两个值都是 FALSE,但只有第一个是。
这里的 logcat
只有我通过 Log.w
写的行。有 3 个组要看:创建首选项和更改第一个首选项,效果很好。然后是第二个 onCreate
,其中两个值据说都是 false
,这是错误的——第一个是真实的——,但设置屏幕显示我确实选中了第一个框.
我对自己做错了什么一无所知。
05-16 13:25:20.290 18778-18778/com.bffmedia.hour11app W/Before switch? Settings
05-16 13:25:20.291 18778-18778/com.bffmedia.hour11app W/Before intent? [
05-16 13:25:20.292 438:0x1a07 I/ActivityManager ]
START u0 {cmp=com.bffmedia.hour11app/.SettingsActivity} from pid 18778
05-16 13:25:20.449 18778-18778/com.bffmedia.hour11app W/back from intent?
05-16 13:25:20.450 18778:0x495a W/after intent ]
false false ***************************** CORRECT ************************
05-16 13:35:16.717 18778-18778/com.bffmedia.hour11app W/onSharedPrefChgd?
true false *********************************** CORRECT
05-16 13:37:21.185 20014-20014/com.bffmedia.hour11app W/Before switch? Settings
05-16 13:37:21.186 20014-20014/com.bffmedia.hour11app W/Before intent? [
05-16 13:37:21.188 438:0x2ef I/ActivityManager ]
START u0 {cmp=com.bffmedia.hour11app/.SettingsActivity} from pid 20014
05-16 13:37:21.245 20014-20014/com.bffmedia.hour11app W/back from intent? [
05-16 13:37:21.245 20014:0x4e2e W/after intent ]
false false *************************************** WHY? *******************************************
这里的问题是您没有查看正确的首选项 xml 文件。来自 PreferenceFragment
的首选项被保存到默认首选项 xml 文件中,并且在您的 MainActivity 中,因为您正在使用 getSharedPreferences(SETTINGS, MODE_PRIVATE)
,另外创建一个新文件到默认首选项 xml 文件。
为了修复它,只需将该代码更改为 PreferenceManager.getDefaultSharedPreferences(this)
,然后您将在 PreferenceFragment
使用的相同首选项 xml 文件中查找。
更多信息here.... and also here.....
这就是您需要做的全部修复工作,我刚刚测试了它,它可以工作!
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
//use this instead:
preferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean firstUse = preferences.getBoolean(FIRST_USE, true);
if (firstUse){
Toast helloMessage = Toast.makeText(getApplicationContext(), "Hello First Time User",Toast.LENGTH_LONG);
helloMessage.show();
editor = preferences.edit();
editor.putBoolean(FIRST_USE, false);
editor.putBoolean ("focus", false);
/*NOTE THE MATCHED STRING vvvvv
<CheckBoxPreference
android:key="focus" android:title="@string/focusAfterShow" android:summary="Always place the cursor" android:defaultValue="false"/> */
editor.putBoolean ("screen", false);
/*NOTE THE MATCHED STRING vvvvvv
<CheckBoxPreference
android:key="screen" android:title="@string/screenSaver" android:summary="Keep screen on" android:defaultValue="false" /> */
editor.commit();
}
else {
///////////////////// problems here *******************
//no need to create another preferences, it's already defined above
//SharedPreferences preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
//This should work now!!!!!!
focusAtClue = preferences.getBoolean("focus",focusAtClue);
screenSaver = preferences.getBoolean("screen",screenSaver);
Log.w("oncreate:", focusAtClue + " " + screenSaver);
Toast helloMessage = Toast.makeText(getApplicationContext(), "Hello Returning User " + focusAtClue + " " + screenSaver,Toast.LENGTH_LONG);
helloMessage.show();
///////////////////// problems
}
}
还有一点需要注意,下面这段代码看起来不会像您想象的那样运行。这段代码的执行不会在调用 startActivity()
时暂停,它会继续执行。因此,您在此处的日志将反映 SharedPreference 在设置 Activity 打开之前的状态,而不是之后。
此外,您也应该在此处使用默认的共享首选项。
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
Log.w("back from intent", "\n");
//preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
preferences = PreferenceManager.getDefaultSharedPreferences(this);
focusAtClue = preferences.getBoolean("focus",true);
screenSaver = preferences.getBoolean("screen",true);
Log.w("after intent", focusAtClue + " " + screenSaver);
return true;