Android中点击按钮后立即更新PreferenceScreen的问题
问题:点击Factory Reset后EditTextPreference的Summary无法即时更新
依赖配置
implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' implementation 'androidx.preference:preference-ktx:1.2.1'
preferences.xml布局
<?xml version="1.0" encoding="utf-8"?> <androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <EditTextPreference android:key="edit_text_preference" android:title="Broadcast IP" app:useSimpleSummaryProvider="true" android:defaultValue="auto" /> <Preference android:title="Factory reset" android:key="@string/myCoolButton" android:summary="Reset all settings" /> </androidx.preference.PreferenceScreen>
注:给EditTextPreference设置了app:useSimpleSummaryProvider="true",让Summary自动显示用户输入内容。
MainActivity.kt代码
class MainActivity : AppCompatActivity() { override fun onCreateOptionsMenu(menu: Menu?): Boolean { val inflater = menuInflater inflater.inflate(R.menu.main_menu, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.getItemId()) { R.id.action_settings -> { val intent = Intent(this, SettingsActivity::class.java) startActivity(intent) true } else -> super.onOptionsItemSelected(item) } } override fun onCreate(savedInstanceState: Bundle?) { // ... 省略原有代码 } override fun onResume() { super.onResume() val sharedPreferences: SharedPreferences = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE) val username = sharedPreferences.getString("key changed", "no change") username?.let { Log.d("code-debug in onresume of main", it) } } }
SettingsActivity.java代码
public class SettingsActivity extends AppCompatActivity { SharedPreferences prefs; SharedPreferences.OnSharedPreferenceChangeListener mylistener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getSupportFragmentManager().beginTransaction() .replace(android.R.id.content, new SettingsFragment()) .commit(); prefs= PreferenceManager.getDefaultSharedPreferences(this); mylistener = new SharedPreferences.OnSharedPreferenceChangeListener() { public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { System.out.println("code-debug : key changed "+ key); SharedPreferences sharedPreferences = getSharedPreferences("MyPrefs", MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString("key changed", key); editor.apply(); } }; prefs.registerOnSharedPreferenceChangeListener(mylistener); } }
SettingsFragment.kt代码
class SettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.preferences, rootKey) val button: Preference? = findPreference(getString(R.string.myCoolButton)) button!!.onPreferenceClickListener = Preference.OnPreferenceClickListener { Log.d("code-debug","you pressed reset all settings") Log.d("code-debug","trying factory reset") val newUsername = "factoryreset" val mysharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) with(mysharedPreferences.edit()) { putString("edit_text_preference", newUsername) apply() } true } } }
问题现象
点击Factory reset按钮后,Broadcast IP对应的EditTextPreference的Summary不会立即更新为"factoryreset",只有返回主界面再重新进入设置页面才能看到变化。
尝试过的无效操作
- 尝试通过Fragment事务刷新:
val ft = parentFragmentManager.beginTransaction() ft.detach(this).attach(this).commit()
无效果。
- 尝试直接设置Summary:
val usernamePreference: EditTextPreference? = findPreference("edit_text_preference") usernamePreference?.let { it.summary = "Current username: JohnDoe" Log.d("code-debug","did you see john doe") }
应用崩溃,报错:
java.lang.IllegalStateException: Preference already has a SummaryProvider set.
- 测试其他Preference:添加CheckBoxPreference后,在按钮点击事件中切换其状态可正常即时更新,说明问题仅出在使用了SimpleSummaryProvider的EditTextPreference上。
解决方案
问题核心是:直接通过SharedPreferences.Editor修改值时,Preference实例无法感知到变化,导致SimpleSummaryProvider不会触发更新。正确做法是直接操作EditTextPreference实例来修改值,而非直接修改SharedPreferences。
修改SettingsFragment中的按钮点击逻辑:
button!!.onPreferenceClickListener = Preference.OnPreferenceClickListener { Log.d("code-debug","you pressed reset all settings") Log.d("code-debug","trying factory reset") val newUsername = "factoryreset" // 直接获取EditTextPreference实例并设置值 val ipPreference = findPreference<EditTextPreference>("edit_text_preference") ipPreference?.setText(newUsername) true }
这种方式会同时更新SharedPreferences和Preference的UI,SimpleSummaryProvider会自动根据新值更新Summary,无需额外操作。
如果坚持要通过SharedPreferences修改,也可以在修改后手动通知Preference数据变化:
// 修改SP之后调用 ipPreference?.notifyChanged()
内容的提问来源于stack exchange,提问作者sumeet inani
相关产品推荐
相关产品推荐

