系统参数的动态刷新,只需一个原则:保持类的无状态

应用系统的开发经常有参数动态刷新的问题,一般的方案会比较复杂,其实只要保持一个原则: 保持类的无状态,那么动态刷新参数是一简很简单的事情. 举下面这个例子.

 

将我们原来的代码:

 

//我们有很多类似这样的UserSerive类,每个类都维护自己的状态,每个类的属性都需要动态刷新
public class UserService {
	private String username; //现username为实例属性,刷新会十分麻烦
	public void setUsername(String v) {
		this.username = v;
	}
	
	public void doSomeThing() {
		loadUserDetail(username);
	}
	
}

 username是一个需要更新的系统参数,而UserSerivce存在spring容器中将username变量注入进来。 那么如果username这个参数需要更改的话会比较麻烦

 

修改为无状态的类:

 

public class StateLessUserService {

	public void doSomeThing2() {
		//实现1: 静态方法得到配置,由Config统一维护参数
		loadUserDetail(Config.getProperty("username"));
	}
}

如实现1,现我们使用一个统一的Config类得到配置参数,只需要刷新该类,那username配置参数即可修改。

这样的好处:

1. 参数的集中式管理

2. 类无状态,参数刷新将十分简单

 

 

再描述一个原则:

既然可以用如此简单的方法达到我们的目的,为何要搞出那么复杂的方案. (简单就是美)

 

<think>我们正在处理一个Android开发问题,用户希望在PreferenceController中更新switchCommonPreference的状态,并实现实时刷新,而不需要退出重进页面。根据用户的问题,我们需要动态更新一个SwitchPreference(switchCommonPreference)的状态,这个状态会根据bottom、mid、top的变化而变化。思路:1.我们需要在PreferenceController中监听影响switchCommonPreference状态的条件(bottom、mid、top)的变化。2.当这些条件变化时,重新计算switchCommonPreference的可用状态(enable/disable)并更新。在Android中,PreferenceController通常用于管理Preference的行为。我们可以通过重写updateState方法来实现状态的更新,因为当首选项显示在屏幕上时,会调用此方法。但是,用户希望的是实时刷新,即在条件改变时立即更新,而不仅仅是在显示时。因此,我们需要在条件变化时主动触发更新。我们可以通过设置一个监听器来监听条件的变化(例如,其他Preference的变化),然后在监听器中更新switchCommonPreference的状态。假设影响switchCommonPreference的条件是其他几个Preference(比如bottomPreference,midPreference,topPreference)的值,我们可以这样做:步骤:1.在PreferenceController的初始化(例如在构造函数或onCreate方法)中获取这些Preference。2.为这些Preference设置OnPreferenceChangeListener。3.在监听器的onPreferenceChange方法中,根据新的值重新计算switchCommonPreference的可用状态,并更新它。但是注意:switchCommonPreference本身可能也需要被监听,所以我们需要确保在更新时不会触发循环。示例代码:假设我们的PreferenceController中有以下成员变量:privateSwitchPreferencemSwitchCommonPreference;privatePreferencemBottomPreference;//可能是任何型的Preference,这里假设是PreferenceprivatePreferencemMidPreference;privatePreferencemTopPreference;在init方法中(或者在onCreatePreferences中)初始化这些Preference并设置监听:注意:以下代码为示例,具体实现可能因你的PreferenceController型(如AbstractPreferenceController或PreferenceFragmentCompat等)而略有不同。```java@OverridepublicvoidonCreatePreferences(BundlesavedInstanceState,StringrootKey){//添加首选项xmlsetPreferencesFromResource(R.xml.your_preferences,rootKey);//初始化PreferencemSwitchCommonPreference=findPreference("key_switch_common");mBottomPreference=findPreference("key_bottom");mMidPreference=findPreference("key_mid");mTopPreference=findPreference("key_top");//设置监听if(mBottomPreference!=null){mBottomPreference.setOnPreferenceChangeListener(mPreferenceChangeListener);}if(mMidPreference!=null){mMidPreference.setOnPreferenceChangeListener(mPreferenceChangeListener);}if(mTopPreference!=null){mTopPreference.setOnPreferenceChangeListener(mPreferenceChangeListener);}}privateOnPreferenceChangeListenermPreferenceChangeListener=newOnPreferenceChangeListener(){@OverridepublicbooleanonPreferenceChange(Preferencepreference,ObjectnewValue){//当任何一个被监听的Preference发生变化时,更新switchCommonPreference的状态updateSwitchCommonState();returntrue;//返回true表示接受新值}};privatevoidupdateSwitchCommonState(){//这里根据bottom、mid、top的当前值来计算switchCommonPreference是否可用//假设我们需要同时满足bottom、mid、top都开启(假设它们都是SwitchPreference,且值为boolean)时,switchCommonPreference才可用booleanbottomEnabled=getPreferenceManager().getSharedPreferences().getBoolean("key_bottom",false);booleanmidEnabled=...;//似booleantopEnabled=...;booleanswitchCommonEnable=bottomEnabled&&midEnabled&&topEnabled;//更新状态mSwitchCommonPreference.setEnabled(switchCommonEnable);//如果需要,还可以更新其他状态,比如可见性、摘要等//mSwitchCommonPreference.setVisible(...);//mSwitchCommonPreference.setSummary(...);}```但是,上面的代码中,我们在监听器中调用了updateSwitchCommonState,这样当任何一个条件Preference改变时,我们都会更新switchCommonPreference的状态。注意:在updateSwitchCommonState中,我们通过SharedPreferences直接获取当前值(因为此时新值还没有保存,所以使用getBoolean获取的是旧值?)。实际上,在onPreferenceChange中,我们还没有将新值保存到SharedPreferences,所以使用SharedPreferences获取的值是旧值。因此,我们需要调整:要么在监听器中使用传入的newValue(但是我们需要知道是哪个Preference变化了,并且还要获取其他Preference的当前值),要么在保存之后更新。方法一:在onPreferenceChange中,我们只标记需要更新,然后在之后更新?但是这样实时性可能不够。方法二:在监听器中,我们分别记录每个Preference的新值(通过参数传入),然后结合其他Preference的当前值(从SharedPreferences中获取)来计算。但是这样逻辑复杂。方法三:在更新SharedPreferences之后,我们可以手动触发更新。但是,在onPreferenceChange中,如果我们返回true,系统会在之后将新值保存到SharedPreferences,然后刷新Preference。但是,此时updateSwitchCommonState中获取的SharedPreferences值可能还是旧的(因为新值还没保存)。所以我们需要在保存之后执行更新。我们可以利用Handler.post来将更新操作放到消息队列的末尾,确保在SharedPreferences更新之后执行:```javaprivateOnPreferenceChangeListenermPreferenceChangeListener=newOnPreferenceChangeListener(){@OverridepublicbooleanonPreferenceChange(Preferencepreference,ObjectnewValue){//使用Handler延迟执行,确保SharedPreferences已经更新newHandler(Looper.getMainLooper()).post(newRunnable(){@Overridepublicvoidrun(){updateSwitchCommonState();}});returntrue;}};```或者,我们可以使用PreferenceScreen的getSharedPreferences()注册一个OnSharedPreferenceChangeListener,这样在SharedPreferences改变后就会触发。但是,这样我们可能需要在多个地方注册和注销,而且需要确保在正确的时间更新。另一种做法是在PreferenceFragment的onResume中注册OnSharedPreferenceChangeListener,在onPause中注销。然后在监听器中调用updateSwitchCommonState。但是,根据用户的需求,我们只需要在条件改变时更新,所以第一种方法(在onPreferenceChange中延迟更新)可能是简单且有效的。总结:在PreferenceController中,我们可以通过为依赖的Preference设置OnPreferenceChangeListener,并在其中使用Handler.post延迟调用更新函数,以确保在SharedPreferences更新后获取到最新的值,然后更新switchCommonPreference的状态。另外,我们还需要在初始的时候设置一次状态(例如在onCreatePreferences中调用一次updateSwitchCommonState)。注意:如果switchCommonPreference的可用状态还依赖于其他条件(比如系统设置),我们可能还需要在系统设置变化时更新,这里我们只考虑其他Preference的影响。最后,如果用户的问题中提到的bottom、mid、top并不是Preference,而是其他型的变量,那么我们需要根据实际情况调整监听方式。例如,如果它们是来自其他模块的数据,我们可能需要使用回调或广播等机制。但是,根据用户的问题上下文,我们假设这些条件是其他Preference。因此,完整的示例代码可能如下:```javapublicclassYourPreferenceControllerextendsAbstractPreferenceControllerimplementsPreference.OnPreferenceChangeListener{privatestaticfinalStringKEY_SWITCH_COMMON="key_switch_common";privatestaticfinalStringKEY_BOTTOM="key_bottom";privatestaticfinalStringKEY_MID="key_mid";privatestaticfinalStringKEY_TOP="key_top";privateSwitchPreferencemSwitchCommonPreference;privateSwitchPreferencemBottomPreference;privateSwitchPreferencemMidPreference;privateSwitchPreferencemTopPreference;publicYourPreferenceController(Contextcontext){super(context);}@OverridepublicvoiddisplayPreference(PreferenceScreenscreen){super.displayPreference(screen);mSwitchCommonPreference=screen.findPreference(KEY_SWITCH_COMMON);mBottomPreference=screen.findPreference(KEY_BOTTOM);mMidPreference=screen.findPreference(KEY_MID);mTopPreference=screen.findPreference(KEY_TOP);//设置监听if(mBottomPreference!=null){mBottomPreference.setOnPreferenceChangeListener(this);}if(mMidPreference!=null){mMidPreference.setOnPreferenceChangeListener(this);}if(mTopPreference!=null){mTopPreference.setOnPreferenceChangeListener(this);}//初始更新updateSwitchCommonState();}@OverridepublicbooleanonPreferenceChange(Preferencepreference,ObjectnewValue){//延迟更新,确保SharedPreferences已经更新newHandler(Looper.getMainLooper()).post(()->updateSwitchCommonState());returntrue;}privatevoidupdateSwitchCommonState(){if(mSwitchCommonPreference==null){return;}//获取当前SharedPreferencesSharedPreferencessharedPreferences=getPreferenceManager().getSharedPreferences();//假设这些Preference都是SwitchPreference,所以默认值为falsebooleanbottomEnabled=sharedPreferences.getBoolean(KEY_BOTTOM,false);booleanmidEnabled=sharedPreferences.getBoolean(KEY_MID,false);booleantopEnabled=sharedPreferences.getBoolean(KEY_TOP,false);booleanswitchCommonEnable=bottomEnabled&&midEnabled&&topEnabled;mSwitchCommonPreference.setEnabled(switchCommonEnable);}//...其他必要的方法,如isAvailable,getPreferenceKey等}```这样,当任何一个条件Preference改变时,switchCommonPreference的状态会实时更新。注意:这里我们假设条件Preference都是SwitchPreference,并且它们的key为KEY_BOTTOM等。请根据实际情况修改。另外,如果条件Preference不是SwitchPreference,那么获取值的方式需要调整(比如可能是ListPreference,那么获取的是字符串)。最后,用户的问题中提到了“bottom、mid和top的变化”,我们假设这些是三个条件,并且它们都是Preference。如果不是,请根据实际情况调整监听方式。希望这能帮助用户解决问题。</think>### 在 PreferenceController 中动态更新 switchCommonPreference 状态的方法 要实现 `switchCommonPreference` 状态的实时刷新,需要结合状态监听和 UI 更新机制。以下是具体步骤和代码实现: #### 1. **状态监听与更新机制** 核心是通过监听 `bottom`/`mid`/`top` 状态变化,触发 `switchCommonPreference` 的实时更新: ```kotlin class PreferenceController : PreferenceController() { private lateinit var switchCommonPreference: SwitchPreferenceCompat // 定义状态变量 private var bottomState: Boolean by observable(false) { _, _, newValue -> updateSwitchState() } private var midState: Boolean by observable(false) { _, _, newValue -> updateSwitchState() } private var topState: Boolean by observable(false) { _, _, newValue -> updateSwitchState() } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.preferences, rootKey) // 初始化 Preference switchCommonPreference = findPreference("key_switch_common")!! // 绑定状态监听 findPreference<SwitchPreferenceCompat>("key_bottom")?.setOnPreferenceChangeListener { _, newValue -> bottomState = newValue as Boolean true } // 为 mid/top 添加似监听器... } private fun updateSwitchState() { // 动态计算新状态(示例逻辑) val newEnabledState = bottomState && (midState || topState) // 实时更新 UI switchCommonPreference.isEnabled = newEnabledState switchCommonPreference.isChecked = newEnabledState // 可选:通知 Preference 框架刷新 notifyHierarchyChanged() } } ``` #### 2. **关键实现点** - **状态驱动 UI**:使用可观察属性(`observable`)监听状态变化,符合状态驱动 UI 的设计原则[^2] - **实时更新**:在状态变化时立即调用 `updateSwitchState()` 更新 UI - **层次刷新**:`notifyHierarchyChanged()` 确保 PreferenceScreen 整体刷新 - **条件计算**:根据业务需求组合 `bottom`/`mid`/`top` 的状态逻辑 #### 3. **优化建议** 1. **防抖处理**(频繁更新时): ```kotlin private val updateHandler = Handler(Looper.getMainLooper()) private fun safeUpdate() { updateHandler.removeCallbacksAndMessages(null) updateHandler.post { updateSwitchState() } } ``` 2. **持久化状态**(如需保存配置): ```kotlin switchCommonPreference.setOnPreferenceChangeListener { _, newValue -> // 保存到 SharedPreferences PreferenceManager.getDefaultSharedPreferences(context) .edit() .putBoolean("key_switch_common", newValue as Boolean) .apply() true } ``` 3. **响应系统主题变化**(深色/浅色模式): ```kotlin override fun onConfigurationChanged(newConfig: Configuration) { // 动态调整状态栏(参考引用[1]) setDarkStatusBar(newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK) updateSwitchState() } private fun setDarkStatusBar(uiMode: Int) { val isDarkMode = uiMode == Configuration.UI_MODE_NIGHT_YES window.decorView.systemUiVisibility = if (isDarkMode) View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR else 0 } ``` #### 4. **注意事项** - **线程安全**:UI 更新必须在主线程执行(使用 `Handler` 或 `runOnUiThread`) - **生命周期**:在 `onStart()`/`onResume()` 中初始化状态,避免空指针 - **性能**:复杂状态计算建议在后台线程处理,结果通过 `LiveData` 传递到 UI > **实现效果**:当 `bottom`/`mid`/`top` 状态变化时,`switchCommonPreference` 会立即更新状态,无需重启页面。该方法同样适用于其他动态 UI 组件[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值