From 5ebd0a8abee6bf6f78e98f4aa0ee1e6aa5aad782 Mon Sep 17 00:00:00 2001 From: johan12345 Date: Fri, 8 Nov 2024 20:50:06 +0100 Subject: [PATCH] fix possible memory leak issues --- app/build.gradle.kts | 2 +- .../vonforst/evmap/fragment/DonateFragment.kt | 3 +- .../java/net/vonforst/evmap/MapsActivity.kt | 21 +++----- .../evmap/fragment/ChargepriceFragment.kt | 12 +++-- .../evmap/fragment/DonateFragmentBase.kt | 30 +++++++++--- .../vonforst/evmap/fragment/MapFragment.kt | 49 +++++++++++-------- .../fragment/preference/AboutFragment.kt | 18 ++++--- 7 files changed, 84 insertions(+), 51 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6df5fc9cd..22bd3d3f6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -317,7 +317,7 @@ dependencies { automotiveImplementation("androidx.car.app:app-automotive:$carAppVersion") // AnyMaps - val anyMapsVersion = "c7ba6ea78d" + val anyMapsVersion = "1174ef9375" implementation("com.github.ev-map.AnyMaps:anymaps-base:$anyMapsVersion") googleImplementation("com.github.ev-map.AnyMaps:anymaps-google:$anyMapsVersion") googleImplementation("com.google.android.gms:play-services-maps:19.0.0") diff --git a/app/src/foss/java/net/vonforst/evmap/fragment/DonateFragment.kt b/app/src/foss/java/net/vonforst/evmap/fragment/DonateFragment.kt index 78f69d02a..c9e7fcb0c 100644 --- a/app/src/foss/java/net/vonforst/evmap/fragment/DonateFragment.kt +++ b/app/src/foss/java/net/vonforst/evmap/fragment/DonateFragment.kt @@ -5,7 +5,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.navigation.ui.setupWithNavController import com.google.android.material.transition.MaterialSharedAxis @@ -43,7 +42,7 @@ class DonateFragment : DonateFragmentBase() { ) binding.btnDonate.setOnClickListener { - (activity as? MapsActivity)?.openUrl(getString(R.string.paypal_link)) + (activity as? MapsActivity)?.openUrl(getString(R.string.paypal_link), binding.root) } setupReferrals(referrals) diff --git a/app/src/main/java/net/vonforst/evmap/MapsActivity.kt b/app/src/main/java/net/vonforst/evmap/MapsActivity.kt index c97c12895..6464d7e04 100644 --- a/app/src/main/java/net/vonforst/evmap/MapsActivity.kt +++ b/app/src/main/java/net/vonforst/evmap/MapsActivity.kt @@ -45,14 +45,11 @@ const val EXTRA_DONATE = "donate" class MapsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { - interface FragmentCallback { - fun getRootView(): View - } private var reenterState: Bundle? = null private lateinit var navController: NavController + private lateinit var navHostFragment: NavHostFragment lateinit var appBarConfiguration: AppBarConfiguration - var fragmentCallback: FragmentCallback? = null private lateinit var prefs: PreferenceDataSource override fun onCreate(savedInstanceState: Bundle?) { @@ -71,7 +68,7 @@ class MapsActivity : AppCompatActivity(), ), drawerLayout ) - val navHostFragment = + navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment navController = navHostFragment.navController val navGraph = navController.navInflater.inflate(R.navigation.nav_graph) @@ -238,7 +235,7 @@ class MapsActivity : AppCompatActivity(), deepLink?.send() } - fun navigateTo(charger: ChargeLocation) { + fun navigateTo(charger: ChargeLocation, rootView: View) { // google maps navigation val coord = charger.coordinates val intent = Intent(Intent.ACTION_VIEW) @@ -248,11 +245,11 @@ class MapsActivity : AppCompatActivity(), startActivity(intent) } else { // fallback: generic geo intent - showLocation(charger) + showLocation(charger, rootView) } } - fun showLocation(charger: ChargeLocation) { + fun showLocation(charger: ChargeLocation, rootView: View) { val coord = charger.coordinates val intent = Intent(Intent.ACTION_VIEW) intent.data = Uri.parse( @@ -263,16 +260,15 @@ class MapsActivity : AppCompatActivity(), if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } else { - val cb = fragmentCallback ?: return Snackbar.make( - cb.getRootView(), + rootView, R.string.no_maps_app_found, Snackbar.LENGTH_SHORT ).show() } } - fun openUrl(url: String, preferBrowser: Boolean = false) { + fun openUrl(url: String, rootView: View, preferBrowser: Boolean = false) { val intent = CustomTabsIntent.Builder() .setDefaultColorSchemeParams( CustomTabColorSchemeParams.Builder() @@ -321,9 +317,8 @@ class MapsActivity : AppCompatActivity(), try { intent.launchUrl(this, uri) } catch (e: ActivityNotFoundException) { - val cb = fragmentCallback ?: return Snackbar.make( - cb.getRootView(), + rootView, R.string.no_browser_app_found, Snackbar.LENGTH_SHORT ).show() diff --git a/app/src/main/java/net/vonforst/evmap/fragment/ChargepriceFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/ChargepriceFragment.kt index b6a129dfb..0de84bfc8 100644 --- a/app/src/main/java/net/vonforst/evmap/fragment/ChargepriceFragment.kt +++ b/app/src/main/java/net/vonforst/evmap/fragment/ChargepriceFragment.kt @@ -141,7 +141,7 @@ class ChargepriceFragment : Fragment() { val chargepriceAdapter = ChargepriceAdapter().apply { onClickListener = { - (requireActivity() as MapsActivity).openUrl(it.url) + (requireActivity() as MapsActivity).openUrl(it.url, binding.root) } } val joinedAdapter = ConcatAdapter( @@ -194,7 +194,10 @@ class ChargepriceFragment : Fragment() { } binding.imgChargepriceLogo.setOnClickListener { - (requireActivity() as MapsActivity).openUrl(ChargepriceApi.getPoiUrl(charger)) + (requireActivity() as MapsActivity).openUrl( + ChargepriceApi.getPoiUrl(charger), + binding.root + ) } binding.btnSettings.setOnClickListener { @@ -217,7 +220,10 @@ class ChargepriceFragment : Fragment() { binding.toolbar.setOnMenuItemClickListener { when (it.itemId) { R.id.menu_help -> { - (activity as? MapsActivity)?.openUrl(getString(R.string.chargeprice_faq_link)) + (activity as? MapsActivity)?.openUrl( + getString(R.string.chargeprice_faq_link), + binding.root + ) true } else -> false diff --git a/app/src/main/java/net/vonforst/evmap/fragment/DonateFragmentBase.kt b/app/src/main/java/net/vonforst/evmap/fragment/DonateFragmentBase.kt index 0432b206e..f5e45536a 100644 --- a/app/src/main/java/net/vonforst/evmap/fragment/DonateFragmentBase.kt +++ b/app/src/main/java/net/vonforst/evmap/fragment/DonateFragmentBase.kt @@ -8,22 +8,40 @@ import net.vonforst.evmap.databinding.FragmentDonateReferralBinding abstract class DonateFragmentBase : Fragment() { fun setupReferrals(referrals: FragmentDonateReferralBinding) { referrals.referralTesla.setOnClickListener { - (requireActivity() as MapsActivity).openUrl(getString(R.string.tesla_referral_link)) + (requireActivity() as MapsActivity).openUrl( + getString(R.string.tesla_referral_link), + requireView() + ) } referrals.referralJuicify.setOnClickListener { - (requireActivity() as MapsActivity).openUrl(getString(R.string.juicify_referral_link)) + (requireActivity() as MapsActivity).openUrl( + getString(R.string.juicify_referral_link), + requireView() + ) } referrals.referralGeldfuereauto.setOnClickListener { - (requireActivity() as MapsActivity).openUrl(getString(R.string.geldfuereauto_referral_link)) + (requireActivity() as MapsActivity).openUrl( + getString(R.string.geldfuereauto_referral_link), + requireView() + ) } referrals.referralMaingau.setOnClickListener { - (requireActivity() as MapsActivity).openUrl(getString(R.string.maingau_referral_link)) + (requireActivity() as MapsActivity).openUrl( + getString(R.string.maingau_referral_link), + requireView() + ) } referrals.referralEwieeinfach.setOnClickListener { - (requireActivity() as MapsActivity).openUrl(getString(R.string.ewieeinfach_referral_link)) + (requireActivity() as MapsActivity).openUrl( + getString(R.string.ewieeinfach_referral_link), + requireView() + ) } referrals.referralEprimo.setOnClickListener { - (requireActivity() as MapsActivity).openUrl(getString(R.string.eprimo_referral_link)) + (requireActivity() as MapsActivity).openUrl( + getString(R.string.eprimo_referral_link), + requireView() + ) } } } \ No newline at end of file diff --git a/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt index 794d74027..1adbb8d53 100644 --- a/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt +++ b/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt @@ -11,6 +11,7 @@ import android.graphics.Color import android.os.Build import android.os.Bundle import android.text.method.KeyListener +import android.util.Log import android.view.ContextThemeWrapper import android.view.Gravity import android.view.LayoutInflater @@ -121,8 +122,9 @@ import kotlin.collections.set import kotlin.math.min -class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallback, MenuProvider { - private lateinit var binding: FragmentMapBinding +class MapFragment : Fragment(), OnMapReadyCallback, MenuProvider { + private var _binding: FragmentMapBinding? = null + private val binding get() = _binding!! private val vm: MapViewModel by viewModels() private val galleryVm: GalleryViewModel by activityViewModels() private var mapFragment: MapFragment? = null @@ -187,7 +189,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac container: ViewGroup?, savedInstanceState: Bundle? ): View { - binding = DataBindingUtil.inflate(inflater, R.layout.fragment_map, container, false) + _binding = DataBindingUtil.inflate(inflater, R.layout.fragment_map, container, false) println(binding.detailView.sourceButton) binding.lifecycleOwner = viewLifecycleOwner binding.vm = vm @@ -362,9 +364,6 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac override fun onResume() { super.onResume() - val hostActivity = activity as? MapsActivity ?: return - hostActivity.fragmentCallback = this - vm.reloadPrefs() if (requestingLocationUpdates && requireContext().checkAnyLocationPermission() ) { @@ -396,7 +395,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac val charger = vm.charger.value?.data if (charger != null) { if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { - (requireActivity() as MapsActivity).navigateTo(charger) + (requireActivity() as MapsActivity).navigateTo(charger, binding.root) } } } @@ -409,7 +408,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac binding.detailView.sourceButton.setOnClickListener { val charger = vm.charger.value?.data if (charger != null) { - (activity as? MapsActivity)?.openUrl(charger.url, true) + (activity as? MapsActivity)?.openUrl(charger.url, binding.root, true) } } binding.detailView.btnChargeprice.setOnClickListener { @@ -422,12 +421,15 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac extras ) } else { - (activity as? MapsActivity)?.openUrl(ChargepriceApi.getPoiUrl(charger)) + (activity as? MapsActivity)?.openUrl( + ChargepriceApi.getPoiUrl(charger), + binding.root + ) } } binding.detailView.btnChargerWebsite.setOnClickListener { val charger = vm.charger.value?.data ?: return@setOnClickListener - charger.chargerUrl?.let { (activity as? MapsActivity)?.openUrl(it) } + charger.chargerUrl?.let { (activity as? MapsActivity)?.openUrl(it, binding.root) } } binding.detailView.btnLogin.setOnClickListener { findNavController().safeNavigate( @@ -435,7 +437,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac ) } binding.detailView.imgPredictionSource.setOnClickListener { - (activity as? MapsActivity)?.openUrl(getString(R.string.fronyx_url)) + (activity as? MapsActivity)?.openUrl(getString(R.string.fronyx_url), binding.root) } binding.detailView.btnPredictionHelp.setOnClickListener { MaterialAlertDialogBuilder(requireContext()) @@ -475,7 +477,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac R.id.menu_edit -> { val charger = vm.charger.value?.data if (charger?.editUrl != null) { - (activity as? MapsActivity)?.openUrl(charger.editUrl, true) + (activity as? MapsActivity)?.openUrl(charger.editUrl, binding.root, true) if (vm.apiId.value == "goingelectric") { // instructions specific to GoingElectric Toast.makeText( @@ -826,10 +828,14 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac if (charger != null) { when (it.icon) { R.drawable.ic_location, R.drawable.ic_address -> { - (activity as? MapsActivity)?.showLocation(charger) + (activity as? MapsActivity)?.showLocation(charger, binding.root) } R.drawable.ic_fault_report -> { - (activity as? MapsActivity)?.openUrl(charger.url, true) + (activity as? MapsActivity)?.openUrl( + charger.url, + binding.root, + true + ) } R.drawable.ic_payment -> { @@ -837,7 +843,12 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac } R.drawable.ic_network -> { - charger.networkUrl?.let { (activity as? MapsActivity)?.openUrl(it) } + charger.networkUrl?.let { + (activity as? MapsActivity)?.openUrl( + it, + binding.root + ) + } } } } @@ -956,7 +967,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac .setTitle(R.string.charge_cards) .setItems(names.toTypedArray()) { _, i -> val card = data[i] - (activity as? MapsActivity)?.openUrl("https:${card.url}") + (activity as? MapsActivity)?.openUrl("https:${card.url}", binding.root) }.show() } @@ -1320,10 +1331,6 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac else -> false } - override fun getRootView(): View { - return binding.root - } - @RequiresPermission(anyOf = [ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION]) private fun requestLocationUpdates() { locationEngine.requestLocationUpdates( @@ -1376,6 +1383,8 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac override fun onDestroyView() { super.onDestroyView() map = null + mapFragment = null + _binding = null vm.mapProjection = null /* if we don't dismiss the popup menu, it will be recreated in some cases (split-screen mode) and then have references to a destroyed fragment. */ diff --git a/app/src/main/java/net/vonforst/evmap/fragment/preference/AboutFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/preference/AboutFragment.kt index 0f2f371f3..c820c822f 100644 --- a/app/src/main/java/net/vonforst/evmap/fragment/preference/AboutFragment.kt +++ b/app/src/main/java/net/vonforst/evmap/fragment/preference/AboutFragment.kt @@ -78,22 +78,25 @@ class AboutFragment : PreferenceFragmentCompat() { } "website" -> { - (activity as? MapsActivity)?.openUrl(getString(R.string.website_url)) + (activity as? MapsActivity)?.openUrl(getString(R.string.website_url), requireView()) true } "github_link" -> { - (activity as? MapsActivity)?.openUrl(getString(R.string.github_link)) + (activity as? MapsActivity)?.openUrl(getString(R.string.github_link), requireView()) true } "privacy" -> { - (activity as? MapsActivity)?.openUrl(getString(R.string.privacy_link)) + (activity as? MapsActivity)?.openUrl( + getString(R.string.privacy_link), + requireView() + ) true } "faq" -> { - (activity as? MapsActivity)?.openUrl(getString(R.string.faq_link)) + (activity as? MapsActivity)?.openUrl(getString(R.string.faq_link), requireView()) true } "oss_licenses" -> { @@ -116,11 +119,14 @@ class AboutFragment : PreferenceFragmentCompat() { true } "twitter" -> { - (activity as? MapsActivity)?.openUrl(getString(R.string.twitter_url)) + (activity as? MapsActivity)?.openUrl(getString(R.string.twitter_url), requireView()) true } "goingelectric" -> { - (activity as? MapsActivity)?.openUrl(getString(R.string.goingelectric_forum_url)) + (activity as? MapsActivity)?.openUrl( + getString(R.string.goingelectric_forum_url), + requireView() + ) true } else -> super.onPreferenceTreeClick(preference)