From c1eb9d6b2a7de3397702ea65308ec6b617f505c1 Mon Sep 17 00:00:00 2001 From: Hugh Daschbach Date: Sat, 26 Aug 2023 15:23:10 -0700 Subject: [PATCH] Fix landscape view induced MainActivity leak. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With landscape view enabled (e.g. e06b2c7) in the app and auto rotation enabled on the phone, switching between portrait and landscape orientations leaks instances of MainActivity. This prevents garbage collection of not just the MainActivity object, but fragments and other objects referenced by the Activity. This is caused by repositories, the AppContext instance, the player service, and authentication code maintaining a reference to the context which with they are initialized. So rather than initialize these with an Activity context, pass them the Application context. Activities are torn down and rebuilt on screen rotation. The Application context is not. To enable instantiation of the FavoritedRepository with the Application context, delay that repository’s initialization until first use. This ensures the Application context is fully initialized. It is not fully initialized until the MainActivity has been fully initialized. --- .../funkwhale/ffa/activities/MainActivity.kt | 17 +++++++++-------- .../audio/funkwhale/ffa/utils/AppContext.kt | 3 +-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt b/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt index f5fe1d8..b3c36b4 100644 --- a/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt +++ b/app/src/main/java/audio/funkwhale/ffa/activities/MainActivity.kt @@ -69,7 +69,9 @@ class MainActivity : AppCompatActivity() { LOGOUT(1001) } - private val favoritedRepository = FavoritedRepository(this) + private val favoritedRepository by lazy { + FavoritedRepository(applicationContext) + } private var menu: Menu? = null private lateinit var binding: ActivityMainBinding @@ -82,8 +84,7 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - AppContext.init(this) - + AppContext.init(applicationContext) binding = ActivityMainBinding.inflate(layoutInflater) (supportFragmentManager.findFragmentById(R.id.now_playing) as NowPlayingFragment).apply { @@ -141,15 +142,15 @@ class MainActivity : AppCompatActivity() { super.onResume() binding.nowPlaying.getFragment().apply { - favoritedRepository.update(this@MainActivity, lifecycleScope) + favoritedRepository.update(applicationContext, lifecycleScope) - startService(Intent(this@MainActivity, PlayerService::class.java)) - DownloadService.start(this@MainActivity, PinService::class.java) + startService(Intent(applicationContext, PlayerService::class.java)) + DownloadService.start(applicationContext, PinService::class.java) CommandBus.send(Command.RefreshService) lifecycleScope.launch(IO) { - Userinfo.get(this@MainActivity, oAuth) + Userinfo.get(applicationContext, oAuth) } } } @@ -343,7 +344,7 @@ class MainActivity : AppCompatActivity() { try { Fuel .post(mustNormalizeUrl("/api/v1/history/listenings/")) - .authorize(this@MainActivity, oAuth) + .authorize(applicationContext, oAuth) .header("Content-Type", "application/json") .body(Gson().toJson(mapOf("track" to track.id))) .awaitStringResponse() diff --git a/app/src/main/java/audio/funkwhale/ffa/utils/AppContext.kt b/app/src/main/java/audio/funkwhale/ffa/utils/AppContext.kt index 7da9415..cacbfed 100644 --- a/app/src/main/java/audio/funkwhale/ffa/utils/AppContext.kt +++ b/app/src/main/java/audio/funkwhale/ffa/utils/AppContext.kt @@ -1,7 +1,6 @@ package audio.funkwhale.ffa.utils import android.annotation.SuppressLint -import android.app.Activity import android.app.NotificationChannel import android.app.NotificationManager import android.content.BroadcastReceiver @@ -23,7 +22,7 @@ object AppContext { const val PAGE_SIZE = 50 const val TRANSITION_DURATION = 300L - fun init(context: Activity) { + fun init(context: Context) { setupNotificationChannels(context) // CastContext.getSharedInstance(context)