From 71f0d98e680f468f8cc891085d2954694dd85198 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Mon, 5 Jan 2026 10:40:55 +0800 Subject: [PATCH] Add SettingsChangeManager and centralize restart logic --- .../java/com/v2ray/ang/handler/MmkvManager.kt | 12 +++---- .../ang/handler/SettingsChangeManager.kt | 32 +++++++++++++++++++ .../v2ray/ang/handler/V2RayServiceManager.kt | 2 +- .../java/com/v2ray/ang/ui/BackupActivity.kt | 4 ++- .../java/com/v2ray/ang/ui/MainActivity.kt | 20 ++++++------ .../com/v2ray/ang/ui/MainRecyclerAdapter.kt | 10 +----- .../com/v2ray/ang/ui/PerAppProxyActivity.kt | 2 ++ .../com/v2ray/ang/ui/PerAppProxyAdapter.kt | 2 ++ .../java/com/v2ray/ang/ui/SubEditActivity.kt | 2 ++ .../v2ray/ang/viewmodel/SettingsViewModel.kt | 2 ++ 10 files changed, 60 insertions(+), 28 deletions(-) create mode 100644 V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsChangeManager.kt diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt index f06c31ac..659bdd16 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MmkvManager.kt @@ -567,10 +567,6 @@ object MmkvManager { return settingsStorage.decodeStringSet(key) } - //endregion - - //region Others - /** * Encodes the start on boot setting. * @@ -594,17 +590,17 @@ object MmkvManager { //region WebDAV /** - * Encodes the WebDAV config as JSON into settings storage. + * Encodes the WebDAV config as JSON into storage. */ fun encodeWebDavConfig(config: WebDavConfig): Boolean { - return settingsStorage.encode(KEY_WEBDAV_CONFIG, JsonUtil.toJson(config)) + return mainStorage.encode(KEY_WEBDAV_CONFIG, JsonUtil.toJson(config)) } /** - * Decodes the WebDAV config from settings storage. + * Decodes the WebDAV config from storage. */ fun decodeWebDavConfig(): WebDavConfig? { - val json = settingsStorage.decodeString(KEY_WEBDAV_CONFIG) ?: return null + val json = mainStorage.decodeString(KEY_WEBDAV_CONFIG) ?: return null return JsonUtil.fromJson(json, WebDavConfig::class.java) } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsChangeManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsChangeManager.kt new file mode 100644 index 00000000..75d0dcc4 --- /dev/null +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsChangeManager.kt @@ -0,0 +1,32 @@ +package com.v2ray.ang.handler + +import kotlinx.coroutines.flow.MutableStateFlow + +object SettingsChangeManager { + private val _restartService = MutableStateFlow(false) + private val _reinitGroupTab = MutableStateFlow(false) + + // Mark restartService as requiring a restart + fun makeRestartService() { + _restartService.value = true + } + + // Read and clear the restartService flag + fun consumeRestartService(): Boolean { + val v = _restartService.value + _restartService.value = false + return v + } + + // Mark reinitGroupTab as requiring tab reinitialization + fun makeReinitGroupTab() { + _reinitGroupTab.value = true + } + + // Read and clear the reinitGroupTab flag + fun consumeReinitGroupTab(): Boolean { + val v = _reinitGroupTab.value + _reinitGroupTab.value = false + return v + } +} diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2RayServiceManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2RayServiceManager.kt index e6d1f983..f14c48c1 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2RayServiceManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/V2RayServiceManager.kt @@ -70,7 +70,7 @@ object V2RayServiceManager { * @param context The context from which the service is stopped. */ fun stopVService(context: Context) { - context.toast(R.string.toast_services_stop) + //context.toast(R.string.toast_services_stop) MessageUtil.sendMsg2Service(context, AppConfig.MSG_STATE_STOP, "") } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BackupActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BackupActivity.kt index 5221fbb5..1e7557f8 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BackupActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/BackupActivity.kt @@ -27,6 +27,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import com.v2ray.ang.databinding.DialogWebdavBinding +import com.v2ray.ang.handler.SettingsChangeManager import com.v2ray.ang.util.ZipUtil import java.io.File import java.text.SimpleDateFormat @@ -169,6 +170,8 @@ class BackupActivity : BaseActivity() { } val count = MMKV.restoreAllFromDirectory(backupDir) + SettingsChangeManager.makeReinitGroupTab() + SettingsChangeManager.makeRestartService() return count > 0 } @@ -312,7 +315,6 @@ class BackupActivity : BaseActivity() { val restored = restoreConfiguration(target) withContext(Dispatchers.Main) { if (restored) { - setResult(RESULT_OK, Intent().putExtra("config_restored", true)) toastSuccess(R.string.toast_success) } else { toastError(R.string.toast_failure) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt index c0e69452..e485cfc8 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt @@ -36,6 +36,7 @@ import com.v2ray.ang.extension.toast import com.v2ray.ang.extension.toastError import com.v2ray.ang.handler.AngConfigManager import com.v2ray.ang.handler.MmkvManager +import com.v2ray.ang.handler.SettingsChangeManager import com.v2ray.ang.helper.SimpleItemTouchHelperCallback import com.v2ray.ang.handler.V2RayServiceManager import com.v2ray.ang.util.Utils @@ -57,7 +58,12 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList } } private val requestActivityLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { - initGroupTab() + if (SettingsChangeManager.consumeRestartService() && mainViewModel.isRunning.value == true) { + restartV2Ray() + } + if (SettingsChangeManager.consumeReinitGroupTab()) { + initGroupTab() + } } private val tabGroupListener = object : TabLayout.OnTabSelectedListener { override fun onTabSelected(tab: TabLayout.Tab?) { @@ -255,7 +261,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList V2RayServiceManager.startVService(this) } - private fun restartV2Ray() { + public fun restartV2Ray() { if (mainViewModel.isRunning.value == true) { V2RayServiceManager.stopVService(this) } @@ -673,14 +679,10 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList // Handle navigation view item clicks here. when (item.itemId) { R.id.sub_setting -> requestActivityLauncher.launch(Intent(this, SubSettingActivity::class.java)) - R.id.per_app_proxy_settings -> startActivity(Intent(this, PerAppProxyActivity::class.java)) + R.id.per_app_proxy_settings -> requestActivityLauncher.launch(Intent(this, PerAppProxyActivity::class.java)) R.id.routing_setting -> requestActivityLauncher.launch(Intent(this, RoutingSettingActivity::class.java)) - R.id.user_asset_setting -> startActivity(Intent(this, UserAssetActivity::class.java)) - R.id.settings -> startActivity( - Intent(this, SettingsActivity::class.java) - .putExtra("isRunning", mainViewModel.isRunning.value == true) - ) - + R.id.user_asset_setting -> requestActivityLauncher.launch(Intent(this, UserAssetActivity::class.java)) + R.id.settings -> requestActivityLauncher.launch(Intent(this, SettingsActivity::class.java)) R.id.promotion -> Utils.openUri(this, "${Utils.decode(AppConfig.APP_PROMOTION_URL)}?t=${System.currentTimeMillis()}") R.id.logcat -> startActivity(Intent(this, LogcatActivity::class.java)) R.id.check_for_update -> startActivity(Intent(this, CheckUpdateActivity::class.java)) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainRecyclerAdapter.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainRecyclerAdapter.kt index 43f32af7..9be24f4c 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainRecyclerAdapter.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainRecyclerAdapter.kt @@ -311,15 +311,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter, blacklist: MutableSet?) : RecyclerView.Adapter() { @@ -83,6 +84,7 @@ class PerAppProxyAdapter(val activity: BaseActivity, val apps: List, bl blacklist.add(appInfo.packageName) itemBypassBinding.checkBox.isChecked = true } + SettingsChangeManager.makeRestartService() } } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubEditActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubEditActivity.kt index f342628d..61c6acb3 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubEditActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SubEditActivity.kt @@ -13,6 +13,7 @@ import com.v2ray.ang.dto.SubscriptionItem import com.v2ray.ang.extension.toast import com.v2ray.ang.extension.toastSuccess import com.v2ray.ang.handler.MmkvManager +import com.v2ray.ang.handler.SettingsChangeManager import com.v2ray.ang.util.Utils import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -30,6 +31,7 @@ class SubEditActivity : BaseActivity() { setContentView(binding.root) title = getString(R.string.title_sub_setting) + SettingsChangeManager.makeReinitGroupTab() val subItem = MmkvManager.decodeSubscription(editSubId) if (subItem != null) { bindingServer(subItem) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt index 78708dbe..c3c8dfa4 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.AndroidViewModel import androidx.preference.PreferenceManager import com.v2ray.ang.AppConfig import com.v2ray.ang.handler.MmkvManager +import com.v2ray.ang.handler.SettingsChangeManager import com.v2ray.ang.handler.SettingsManager class SettingsViewModel(application: Application) : AndroidViewModel(application), @@ -100,5 +101,6 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application if (key == AppConfig.PREF_UI_MODE_NIGHT) { SettingsManager.setNightMode() } + SettingsChangeManager.makeRestartService() } }