From fe69a78b941af2970d2667451e9bf428d6b4e778 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 | 46 +++++++++++-------- .../fragment/preference/AboutFragment.kt | 18 +++++--- 7 files changed, 81 insertions(+), 51 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 72e280c6c..4b44a8178 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -315,7 +315,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 0b63dd14b..7ed3dc59a 100644 --- a/app/src/main/java/net/vonforst/evmap/MapsActivity.kt +++ b/app/src/main/java/net/vonforst/evmap/MapsActivity.kt @@ -44,14 +44,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?) { @@ -70,7 +67,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) @@ -237,7 +234,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) @@ -247,11 +244,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( @@ -262,16 +259,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 = true) { + fun openUrl(url: String, rootView: View, preferBrowser: Boolean = true) { val pkg = CustomTabsClient.getPackageName(this, null) val intent = CustomTabsIntent.Builder() .setDefaultColorSchemeParams( @@ -288,9 +284,8 @@ class MapsActivity : AppCompatActivity(), try { intent.launchUrl(this, Uri.parse(url)) } 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 584841731..bc762c292 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 @@ -137,8 +138,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 @@ -212,7 +214,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 @@ -391,9 +393,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() ) { @@ -425,7 +424,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) } } } @@ -438,7 +437,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) + (activity as? MapsActivity)?.openUrl(charger.url, binding.root) } } binding.detailView.btnChargeprice.setOnClickListener { @@ -451,12 +450,16 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac extras ) } else { - (activity as? MapsActivity)?.openUrl(ChargepriceApi.getPoiUrl(charger), false) + (activity as? MapsActivity)?.openUrl( + ChargepriceApi.getPoiUrl(charger), + binding.root, + false + ) } } 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( @@ -464,7 +467,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()) @@ -504,7 +507,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) + (activity as? MapsActivity)?.openUrl(charger.editUrl, binding.root) if (vm.apiId.value == "goingelectric") { // instructions specific to GoingElectric Toast.makeText( @@ -920,10 +923,10 @@ 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) + (activity as? MapsActivity)?.openUrl(charger.url, binding.root) } R.drawable.ic_payment -> { @@ -931,7 +934,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 + ) + } } } } @@ -1050,7 +1058,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() } @@ -1540,10 +1548,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( @@ -1596,6 +1600,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)