You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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",只有返回主界面再重新进入设置页面才能看到变化。

尝试过的无效操作

  1. 尝试通过Fragment事务刷新:
val ft = parentFragmentManager.beginTransaction() 
ft.detach(this).attach(this).commit()

无效果。

  1. 尝试直接设置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.
  1. 测试其他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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:24:57