From 4205fc41b76aa67d6c50f7cb5c16fc81c89915d4 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Mon, 24 Mar 2025 17:58:22 +0530 Subject: [PATCH] Fixed: `testOpeningFileWithFilePicker` test intermittently fails on API level 34. * Fixed: Memory leaks in `OnlineLibraryFragment` that appeared after upgrading LeakCanary. * Fixed: Memory leaks in `LocalFileTransferFragment` that appeared after upgrading LeakCanary. * Fixed: A memory leak in `ZimManageViewModel` caused by `addNetworkInterceptor` holding a reference to progressListener. --- .../OpeningFilesFromStorageTest.kt | 2 +- .../LocalFileTransferFragment.kt | 1 + .../library/OnlineLibraryFragment.kt | 21 ++++++++++++------- .../zimManager/ZimManageViewModel.kt | 7 +++++-- .../core/data/remote/ProgressResponseBody.kt | 4 ++-- .../kiwixmobile/core/page/PageFragment.kt | 5 ++++- 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/localLibrary/OpeningFilesFromStorageTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/localLibrary/OpeningFilesFromStorageTest.kt index 5866929f9..954398538 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/localLibrary/OpeningFilesFromStorageTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/localLibrary/OpeningFilesFromStorageTest.kt @@ -117,7 +117,7 @@ class OpeningFilesFromStorageTest : BaseActivityTest() { sharedPreferenceUtil.shouldShowStorageSelectionDialog = true // open file picker to select a file to test the real scenario. composeTestRule.onNodeWithTag(SELECT_FILE_BUTTON_TESTING_TAG).performClick() - uiDevice.findObject(By.textContains(fileName)).click() + TestUtils.testFlakyView(uiDevice.findObject(By.textContains(fileName))::click, 10) copyMoveFileHandler { assertCopyMoveDialogDisplayed() diff --git a/app/src/main/java/org/kiwix/kiwixmobile/localFileTransfer/LocalFileTransferFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/localFileTransfer/LocalFileTransferFragment.kt index 5b0bcd082..6d37a45fb 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/localFileTransfer/LocalFileTransferFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/localFileTransfer/LocalFileTransferFragment.kt @@ -533,6 +533,7 @@ class LocalFileTransferFragment : override fun onDestroyView() { wifiDirectManager.stopWifiDirectManager() wifiDirectManager.callbacks = null + fragmentLocalFileTransferBinding?.root?.removeAllViews() fragmentLocalFileTransferBinding = null searchIconView = null materialShowCaseSequence = null diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/OnlineLibraryFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/OnlineLibraryFragment.kt index c51e2f387..9047c65cb 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/OnlineLibraryFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/OnlineLibraryFragment.kt @@ -227,13 +227,13 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions { setupMenu() // hides keyboard when scrolled - fragmentDestinationDownloadBinding?.libraryList?.addOnScrollListener( - SimpleRecyclerViewScrollListener { _, newState -> - if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { - fragmentDestinationDownloadBinding?.libraryList?.closeKeyboard() - } - } - ) + fragmentDestinationDownloadBinding?.libraryList?.addOnScrollListener(simpleScrollListener) + } + + private var simpleScrollListener = SimpleRecyclerViewScrollListener { _, newState -> + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + fragmentDestinationDownloadBinding?.libraryList?.closeKeyboard() + } } private fun setupMenu() { @@ -373,7 +373,12 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions { override fun onDestroyView() { super.onDestroyView() - fragmentDestinationDownloadBinding?.libraryList?.adapter = null + fragmentDestinationDownloadBinding?.apply { + librarySwipeRefresh.setOnRefreshListener(null) + libraryList.removeOnScrollListener(simpleScrollListener) + libraryList.adapter = null + root.removeAllViews() + } fragmentDestinationDownloadBinding = null } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/ZimManageViewModel.kt b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/ZimManageViewModel.kt index 46e7d9d1c..61742611f 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/ZimManageViewModel.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/ZimManageViewModel.kt @@ -181,7 +181,7 @@ class ZimManageViewModel @Inject constructor( .body( ProgressResponseBody( responseBody, - AppProgressListenerProvider(this), + appProgressListener, contentLength ) ) @@ -195,6 +195,8 @@ class ZimManageViewModel @Inject constructor( } } + private var appProgressListener: AppProgressListenerProvider? = AppProgressListenerProvider(this) + private fun getContentLengthOfLibraryXmlFile(): Long { val headRequest = Request.Builder() @@ -218,7 +220,7 @@ class ZimManageViewModel @Inject constructor( ?: DEFAULT_INT_VALUE.toLong() } } - } catch (ignore: Exception) { + } catch (_: Exception) { // do nothing } return DEFAULT_INT_VALUE.toLong() @@ -237,6 +239,7 @@ class ZimManageViewModel @Inject constructor( fileSelectActions.onComplete() requestDownloadLibrary.onComplete() compositeDisposable = null + appProgressListener = null super.onCleared() } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/remote/ProgressResponseBody.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/remote/ProgressResponseBody.kt index d59e0f9b0..4d9869df2 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/remote/ProgressResponseBody.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/remote/ProgressResponseBody.kt @@ -30,7 +30,7 @@ import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO class ProgressResponseBody( private val responseBody: ResponseBody, - private val progressListener: OnlineLibraryProgressListener, + private val progressListener: OnlineLibraryProgressListener?, private val contentLength: Long ) : ResponseBody() { private lateinit var bufferedSource: BufferedSource @@ -51,7 +51,7 @@ class ProgressResponseBody( override fun read(sink: Buffer, byteCount: Long): Long { val bytesRead = super.read(sink, byteCount) totalBytesRead += if (bytesRead != DEFAULT_INT_VALUE.toLong()) bytesRead else ZERO.toLong() - progressListener.onProgress(totalBytesRead, contentLength) + progressListener?.onProgress(totalBytesRead, contentLength) return bytesRead } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/PageFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/PageFragment.kt index 30b5515ab..b5af06fd3 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/PageFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/PageFragment.kt @@ -189,7 +189,10 @@ abstract class PageFragment : OnItemClickListener, BaseFragment(), FragmentActiv override fun onDestroyView() { super.onDestroyView() compositeDisposable.clear() - fragmentPageBinding?.recyclerView?.adapter = null + fragmentPageBinding?.apply { + recyclerView.adapter = null + root.removeAllViews() + } fragmentPageBinding = null }