From 5e98d2cbe190b8d5d8351fe0240fed19eb1c16d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Wed, 6 Sep 2023 19:57:56 +0800 Subject: [PATCH] Fix binding usage --- .../sfa/ui/dashboard/GroupsFragment.kt | 21 +++++++++----- .../sfa/ui/dashboard/OverviewFragment.kt | 18 +++++++----- .../sfa/ui/main/DashboardFragment.kt | 15 +++++++--- .../io/nekohasekai/sfa/ui/main/LogFragment.kt | 10 ++++--- .../sfa/ui/profile/EditProfileActivity.kt | 29 ++++++++++++++----- .../ui/profile/EditProfileContentActivity.kt | 14 ++++++--- .../sfa/ui/profile/NewProfileActivity.kt | 15 +++++++--- 7 files changed, 84 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/io/nekohasekai/sfa/ui/dashboard/GroupsFragment.kt b/app/src/main/java/io/nekohasekai/sfa/ui/dashboard/GroupsFragment.kt index 220204c..949b958 100644 --- a/app/src/main/java/io/nekohasekai/sfa/ui/dashboard/GroupsFragment.kt +++ b/app/src/main/java/io/nekohasekai/sfa/ui/dashboard/GroupsFragment.kt @@ -37,12 +37,8 @@ import kotlinx.coroutines.withContext class GroupsFragment : Fragment(), CommandClient.Handler { private val activity: MainActivity? get() = super.getActivity() as MainActivity? - private var _binding: FragmentDashboardGroupsBinding? = null - private val binding get() = _binding!! - - private var _adapter: Adapter? = null - private val adapter get() = _adapter!! - + private var binding: FragmentDashboardGroupsBinding? = null + private var adapter: Adapter? = null private val commandClient = CommandClient(lifecycleScope, CommandClient.ConnectionType.Groups, this) @@ -50,14 +46,16 @@ class GroupsFragment : Fragment(), CommandClient.Handler { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - _binding = FragmentDashboardGroupsBinding.inflate(inflater, container, false) + val binding = FragmentDashboardGroupsBinding.inflate(inflater, container, false) + this.binding = binding onCreate() return binding.root } private fun onCreate() { val activity = activity ?: return - _adapter = Adapter() + val binding = binding ?: return + adapter = Adapter() binding.container.adapter = adapter binding.container.layoutManager = LinearLayoutManager(requireContext()) activity.serviceStatus.observe(viewLifecycleOwner) { @@ -67,8 +65,14 @@ class GroupsFragment : Fragment(), CommandClient.Handler { } } + override fun onDestroyView() { + super.onDestroyView() + binding = null + } + private var displayed = false private fun updateDisplayed(newValue: Boolean) { + val binding = binding ?: return if (displayed != newValue) { displayed = newValue binding.statusText.isVisible = !displayed @@ -90,6 +94,7 @@ class GroupsFragment : Fragment(), CommandClient.Handler { @SuppressLint("NotifyDataSetChanged") override fun updateGroups(groups: List) { + val adapter = adapter ?: return activity?.runOnUiThread { updateDisplayed(groups.isNotEmpty()) adapter.groups = groups diff --git a/app/src/main/java/io/nekohasekai/sfa/ui/dashboard/OverviewFragment.kt b/app/src/main/java/io/nekohasekai/sfa/ui/dashboard/OverviewFragment.kt index c3aa20c..d98ed13 100644 --- a/app/src/main/java/io/nekohasekai/sfa/ui/dashboard/OverviewFragment.kt +++ b/app/src/main/java/io/nekohasekai/sfa/ui/dashboard/OverviewFragment.kt @@ -37,8 +37,7 @@ import kotlinx.coroutines.withContext class OverviewFragment : Fragment() { private val activity: MainActivity? get() = super.getActivity() as MainActivity? - private var _binding: FragmentDashboardOverviewBinding? = null - private val binding get() = _binding!! + private var binding: FragmentDashboardOverviewBinding? = null private val statusClient = CommandClient(lifecycleScope, CommandClient.ConnectionType.Status, StatusClient()) private val clashModeClient = @@ -48,13 +47,15 @@ class OverviewFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - _binding = FragmentDashboardOverviewBinding.inflate(inflater, container, false) + val binding = FragmentDashboardOverviewBinding.inflate(inflater, container, false) + this.binding = binding onCreate() return binding.root } private fun onCreate() { val activity = activity ?: return + val binding = binding ?: return binding.profileList.adapter = Adapter(lifecycleScope, binding).apply { adapter = this reload() @@ -81,7 +82,7 @@ class OverviewFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() adapter = null - _binding = null + binding = null statusClient.disconnect() clashModeClient.disconnect() ProfileManager.unregisterCallback(this::updateProfiles) @@ -92,6 +93,7 @@ class OverviewFragment : Fragment() { } private fun reloadSystemProxyStatus() { + val binding = binding ?: return lifecycleScope.launch(Dispatchers.IO) { val status = Libbox.newStandaloneCommandClient().systemProxyStatus withContext(Dispatchers.Main) { @@ -117,7 +119,7 @@ class OverviewFragment : Fragment() { inner class StatusClient : CommandClient.Handler { override fun onConnected() { - val binding = _binding ?: return + val binding = binding ?: return lifecycleScope.launch(Dispatchers.Main) { binding.memoryText.text = getString(R.string.loading) binding.goroutinesText.text = getString(R.string.loading) @@ -125,7 +127,7 @@ class OverviewFragment : Fragment() { } override fun onDisconnected() { - val binding = _binding ?: return + val binding = binding ?: return lifecycleScope.launch(Dispatchers.Main) { binding.memoryText.text = getString(R.string.loading) binding.goroutinesText.text = getString(R.string.loading) @@ -133,7 +135,7 @@ class OverviewFragment : Fragment() { } override fun updateStatus(status: StatusMessage) { - val binding = _binding ?: return + val binding = binding ?: return lifecycleScope.launch(Dispatchers.Main) { binding.memoryText.text = Libbox.formatBytes(status.memory) binding.goroutinesText.text = status.goroutines.toString() @@ -155,6 +157,7 @@ class OverviewFragment : Fragment() { inner class ClashModeClient : CommandClient.Handler { override fun initializeClashMode(modeList: List, currentMode: String) { + val binding = binding ?: return if (modeList.size > 1) { lifecycleScope.launch(Dispatchers.Main) { binding.clashModeCard.isVisible = true @@ -174,6 +177,7 @@ class OverviewFragment : Fragment() { @SuppressLint("NotifyDataSetChanged") override fun updateClashMode(newMode: String) { + val binding = binding ?: return val adapter = binding.clashModeList.adapter as? ClashModeAdapter ?: return adapter.selected = newMode lifecycleScope.launch(Dispatchers.Main) { diff --git a/app/src/main/java/io/nekohasekai/sfa/ui/main/DashboardFragment.kt b/app/src/main/java/io/nekohasekai/sfa/ui/main/DashboardFragment.kt index be3feda..fd336fa 100644 --- a/app/src/main/java/io/nekohasekai/sfa/ui/main/DashboardFragment.kt +++ b/app/src/main/java/io/nekohasekai/sfa/ui/main/DashboardFragment.kt @@ -20,19 +20,19 @@ import io.nekohasekai.sfa.ui.dashboard.OverviewFragment class DashboardFragment : Fragment(R.layout.fragment_dashboard) { private val activity: MainActivity? get() = super.getActivity() as MainActivity? - private var _binding: FragmentDashboardBinding? = null - private val binding get() = _binding!! - + private var binding: FragmentDashboardBinding? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - _binding = FragmentDashboardBinding.inflate(inflater, container, false) + val binding = FragmentDashboardBinding.inflate(inflater, container, false) + this.binding = binding onCreate() return binding.root } private fun onCreate() { val activity = activity ?: return + val binding = binding ?: return binding.dashboardPager.adapter = Adapter(this) binding.dashboardPager.offscreenPageLimit = Page.values().size TabLayoutMediator(binding.dashboardTabLayout, binding.dashboardPager) { tab, position -> @@ -79,12 +79,19 @@ class DashboardFragment : Fragment(R.layout.fragment_dashboard) { } } + override fun onDestroyView() { + super.onDestroyView() + binding = null + } + private fun enablePager() { + val binding = binding ?: return binding.dashboardTabLayout.isVisible = true binding.dashboardPager.isUserInputEnabled = true } private fun disablePager() { + val binding = binding ?: return binding.dashboardTabLayout.isVisible = false binding.dashboardPager.isUserInputEnabled = false binding.dashboardPager.setCurrentItem(0, false) diff --git a/app/src/main/java/io/nekohasekai/sfa/ui/main/LogFragment.kt b/app/src/main/java/io/nekohasekai/sfa/ui/main/LogFragment.kt index b15efe1..a61fb83 100644 --- a/app/src/main/java/io/nekohasekai/sfa/ui/main/LogFragment.kt +++ b/app/src/main/java/io/nekohasekai/sfa/ui/main/LogFragment.kt @@ -19,20 +19,21 @@ import java.util.LinkedList class LogFragment : Fragment() { private val activity: MainActivity? get() = super.getActivity() as MainActivity? - private var _binding: FragmentLogBinding? = null - private val binding get() = _binding!! + private var binding: FragmentLogBinding? = null private var logAdapter: LogAdapter? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - _binding = FragmentLogBinding.inflate(inflater, container, false) + val binding = FragmentLogBinding.inflate(inflater, container, false) + this.binding = binding onCreate() return binding.root } private fun onCreate() { val activity = activity ?: return + val binding = binding ?: return activity.logCallback = ::updateViews binding.logView.layoutManager = LinearLayoutManager(requireContext()) binding.logView.adapter = LogAdapter(activity.logList).also { logAdapter = it } @@ -82,6 +83,7 @@ class LogFragment : Fragment() { private fun updateViews(reset: Boolean) { val activity = activity ?: return val logAdapter = logAdapter ?: return + val binding = binding ?: return if (activity.logList.isEmpty()) { binding.logView.isVisible = false binding.statusText.isVisible = true @@ -99,7 +101,7 @@ class LogFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() - _binding = null + binding = null activity?.logCallback = null logAdapter = null } diff --git a/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileActivity.kt b/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileActivity.kt index 93846a5..6a4fe3f 100644 --- a/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileActivity.kt +++ b/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileActivity.kt @@ -30,15 +30,15 @@ import java.util.Date class EditProfileActivity : AbstractActivity() { - private var _binding: ActivityEditProfileBinding? = null - private val binding get() = _binding!! + private var binding: ActivityEditProfileBinding? = null private var _profile: Profile? = null private val profile get() = _profile!! override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setTitle(R.string.title_edit_profile) - _binding = ActivityEditProfileBinding.inflate(layoutInflater) + val binding = ActivityEditProfileBinding.inflate(layoutInflater) + this.binding = binding setContentView(binding.root) supportActionBar?.setDisplayHomeAsUpEnabled(true) @@ -46,14 +46,22 @@ class EditProfileActivity : AbstractActivity() { runCatching { loadProfile() }.onFailure { - errorDialogBuilder(it) - .setPositiveButton(android.R.string.ok) { _, _ -> finish() } - .show() + withContext(Dispatchers.Main) { + errorDialogBuilder(it) + .setPositiveButton(android.R.string.ok) { _, _ -> finish() } + .show() + } } } } + override fun onDestroy() { + super.onDestroy() + binding = null + } + private suspend fun loadProfile() { + val binding = binding ?: return delay(200L) val profileId = intent.getLongExtra("profile_id", -1L) @@ -67,7 +75,9 @@ class EditProfileActivity : AbstractActivity() { profile.name = it ProfileManager.update(profile) } catch (e: Exception) { - errorDialogBuilder(e).show() + withContext(Dispatchers.Main) { + errorDialogBuilder(e).show() + } } } } @@ -120,6 +130,7 @@ class EditProfileActivity : AbstractActivity() { } private fun updateAutoUpdate(newValue: String) { + val binding = binding ?: return val boolValue = EnabledType.valueOf(newValue).boolValue if (profile.typed.autoUpdate == boolValue) { return @@ -135,6 +146,7 @@ class EditProfileActivity : AbstractActivity() { } private fun updateAutoUpdateInterval(newValue: String) { + val binding = binding ?: return if (newValue.isBlank()) { binding.autoUpdateInterval.error = getString(R.string.profile_input_required) return @@ -156,6 +168,7 @@ class EditProfileActivity : AbstractActivity() { } private fun updateProfile() { + val binding = binding ?: return binding.progressView.isVisible = true lifecycleScope.launch(Dispatchers.IO) { delay(200) @@ -173,6 +186,7 @@ class EditProfileActivity : AbstractActivity() { } private fun updateProfile(view: View) { + val binding = binding ?: return binding.progressView.isVisible = true lifecycleScope.launch(Dispatchers.IO) { try { @@ -195,6 +209,7 @@ class EditProfileActivity : AbstractActivity() { } private fun checkProfile(button: View) { + val binding = binding ?: return binding.progressView.isVisible = true lifecycleScope.launch(Dispatchers.IO) { delay(200) diff --git a/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileContentActivity.kt b/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileContentActivity.kt index 6df964f..876ab85 100644 --- a/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileContentActivity.kt +++ b/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileContentActivity.kt @@ -23,22 +23,26 @@ import java.io.File class EditProfileContentActivity : AbstractActivity() { - private var _binding: ActivityEditProfileContentBinding? = null - private val binding get() = _binding!! - + private var binding: ActivityEditProfileContentBinding? = null private var _profile: Profile? = null private val profile get() = _profile!! override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setTitle(R.string.title_edit_configuration) - _binding = ActivityEditProfileContentBinding.inflate(layoutInflater) + val binding = ActivityEditProfileContentBinding.inflate(layoutInflater) + this.binding = binding setContentView(binding.root) supportActionBar?.setDisplayHomeAsUpEnabled(true) binding.editor.language = JsonLanguage() loadConfiguration() } + override fun onDestroy() { + super.onDestroy() + binding = null + } + private fun loadConfiguration() { lifecycleScope.launch(Dispatchers.IO) { runCatching { @@ -59,6 +63,7 @@ class EditProfileContentActivity : AbstractActivity() { } override fun onOptionsItemSelected(item: MenuItem): Boolean { + val binding = binding ?: return false when (item.itemId) { R.id.action_undo -> { if (binding.editor.canUndo()) binding.editor.undo() @@ -110,6 +115,7 @@ class EditProfileContentActivity : AbstractActivity() { } private suspend fun loadConfiguration0() { + val binding = binding ?: return delay(200L) val profileId = intent.getLongExtra("profile_id", -1L) diff --git a/app/src/main/java/io/nekohasekai/sfa/ui/profile/NewProfileActivity.kt b/app/src/main/java/io/nekohasekai/sfa/ui/profile/NewProfileActivity.kt index 2e0fc70..ad4eace 100644 --- a/app/src/main/java/io/nekohasekai/sfa/ui/profile/NewProfileActivity.kt +++ b/app/src/main/java/io/nekohasekai/sfa/ui/profile/NewProfileActivity.kt @@ -33,11 +33,10 @@ class NewProfileActivity : AbstractActivity() { Import("Import"); } - private var _binding: ActivityAddProfileBinding? = null - private val binding get() = _binding!! - + private var binding: ActivityAddProfileBinding? = null private val importFile = registerForActivityResult(ActivityResultContracts.GetContent()) { fileURI -> + val binding = binding ?: return@registerForActivityResult if (fileURI != null) { binding.sourceURL.editText?.setText(fileURI.toString()) } @@ -47,7 +46,8 @@ class NewProfileActivity : AbstractActivity() { super.onCreate(savedInstanceState) setTitle(R.string.title_new_profile) - _binding = ActivityAddProfileBinding.inflate(layoutInflater) + val binding = ActivityAddProfileBinding.inflate(layoutInflater) + this.binding = binding setContentView(binding.root) supportActionBar?.setDisplayHomeAsUpEnabled(true) @@ -91,7 +91,13 @@ class NewProfileActivity : AbstractActivity() { } } + override fun onDestroy() { + super.onDestroy() + binding = null + } + private fun createProfile(view: View) { + val binding = binding ?: return if (binding.name.showErrorIfEmpty()) { return } @@ -126,6 +132,7 @@ class NewProfileActivity : AbstractActivity() { } private suspend fun createProfile0() { + val binding = binding ?: return val typedProfile = TypedProfile() val profile = Profile(name = binding.name.text, typed = typedProfile) profile.userOrder = ProfileManager.nextOrder()