设计抉择:在PreferencesActivity中用Broadcast Receiver还是静态类?
兄弟,我太懂你这种PreferenceActivity代码越写越臃肿的糟心了!把服务启停、数据库连接这些杂七杂八的逻辑全堆在Activity里,后期改个需求都得翻半天代码。给你几个亲测好用的拆分方案,帮你把代码捋得明明白白:
1. 用独立的PreferenceChangeListener抽离单偏好逻辑
把每个偏好选项对应的操作封装成独立的OnSharedPreferenceChangeListener实现类,让Activity只负责注册监听器,不用管具体逻辑:
// 专门处理同步开关的监听器 public class SyncToggleListener implements SharedPreferences.OnSharedPreferenceChangeListener { private Context mContext; public SyncToggleListener(Context context) { mContext = context; } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if ("pref_key_sync_enabled".equals(key)) { boolean isSyncEnabled = sharedPreferences.getBoolean(key, false); if (isSyncEnabled) { // 开启同步服务 startSyncService(); // 初始化数据库连接 initDatabaseConnection(); } else { // 关闭同步服务 stopSyncService(); // 断开数据库连接 closeDatabaseConnection(); } } } private void startSyncService() { Intent serviceIntent = new Intent(mContext, SyncService.class); ContextCompat.startForegroundService(mContext, serviceIntent); } private void stopSyncService() { Intent serviceIntent = new Intent(mContext, SyncService.class); mContext.stopService(serviceIntent); } private void initDatabaseConnection() { // 这里写数据库连接初始化逻辑 } private void closeDatabaseConnection() { // 这里写数据库连接关闭逻辑 } }
然后在PreferenceActivity里只需注册:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); prefs.registerOnSharedPreferenceChangeListener(new SyncToggleListener(this)); }
这样每个偏好的逻辑都独立成类,代码结构清晰,后期修改某一个选项的逻辑也不会影响其他部分。
2. 用ViewModel分离全局业务逻辑
如果你的项目已经用了Jetpack组件,那用ViewModel来承载业务逻辑是更优的选择。ViewModel可以和Activity生命周期绑定,还能避免内存泄漏:
public class SettingsViewModel extends ViewModel { private SharedPreferences mPrefs; private Context mContext; public void init(Context context, SharedPreferences prefs) { mContext = context.getApplicationContext(); mPrefs = prefs; mPrefs.registerOnSharedPreferenceChangeListener(mPrefChangeListener); } private final SharedPreferences.OnSharedPreferenceChangeListener mPrefChangeListener = (sharedPreferences, key) -> { switch (key) { case "pref_key_notifications": toggleNotifications(sharedPreferences.getBoolean(key, true)); break; case "pref_key_sync_enabled": handleSyncToggle(sharedPreferences.getBoolean(key, false)); break; // 其他偏好选项的处理 } }; private void toggleNotifications(boolean enabled) { // 处理通知开关的逻辑,比如注册/取消广播接收器 } private void handleSyncToggle(boolean enabled) { // 这里调用服务和数据库操作的工具方法 if (enabled) { ServiceHelper.startSyncService(mContext); DbHelper.initConnection(); } else { ServiceHelper.stopSyncService(mContext); DbHelper.closeConnection(); } } @Override protected void onCleared() { super.onCleared(); // 页面销毁时取消监听器注册,避免内存泄漏 mPrefs.unregisterOnSharedPreferenceChangeListener(mPrefChangeListener); } }
Activity里的代码就变得非常简洁:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); SettingsViewModel viewModel = new ViewModelProvider(this).get(SettingsViewModel.class); viewModel.init(this, getPreferenceManager().getSharedPreferences()); }
3. 用工具类封装通用操作
把开启服务、数据库连接这些重复的通用逻辑抽成工具类,让Listener或ViewModel只负责调用,不用重复写实现:
// 服务操作工具类 public class ServiceHelper { private ServiceHelper() {} // 私有构造,避免实例化 public static void startSyncService(Context context) { Intent intent = new Intent(context, SyncService.class); ContextCompat.startForegroundService(context, intent); } public static void stopSyncService(Context context) { Intent intent = new Intent(context, SyncService.class); context.stopService(intent); } } // 数据库操作工具类 public class DbHelper { private static DbConnection sConnection; public static void initConnection() { if (sConnection == null) { // 初始化数据库连接 sConnection = new DbConnection(); } } public static void closeConnection() { if (sConnection != null) { sConnection.close(); sConnection = null; } } }
这样不管是在Listener还是ViewModel里,都可以一行代码搞定操作,代码复用性拉满。
4. 建议迁移到PreferenceFragmentCompat
虽然你现在用的是PreferenceActivity,但如果有机会的话,建议迁移到PreferenceFragmentCompat。它是AndroidX提供的更现代的偏好组件,支持动态加载偏好布局,还能把不同类别的偏好拆成多个Fragment,进一步拆分逻辑,和Jetpack组件的兼容性也更好。
核心思路总结
不管用哪种方案,核心都是把UI层(PreferenceActivity/Fragment)和业务逻辑层彻底分离:让Activity只做和UI相关的事(加载布局、注册监听器),把服务启停、数据库操作这些业务逻辑放到专门的类里。这样不仅能大幅减少Activity的代码量,后期维护、扩展也会轻松很多。
内容的提问来源于stack exchange,提问作者10101010

