Skip to content

Conversation

@largeblueberry
Copy link
Contributor

Purpose / Description

This PR addresses the memory leak issues in SharedDecksActivity related to WebView usage, as identified in #19965.

Following the experimental fix suggestions, I implemented the onDestroy() method in SharedDecksActivity and incorporated the cleanup logic based on the pattern found in SafeWebViewLayout.safeDestroy()

Fixes

Approach

The focus of this change is to ensure that the WebView is properly disposed of when the Activity is destroyed. I ported the cleanup sequence from SafeWebViewLayout:

  • Stopped ongoing loading and cleared the WebView by loading about:blank.
  • Nullified WebChromeClient and OnScrollChangeListener to break reference cycles.
  • Detached the WebView from its parent ViewGroup before final destruction.
  • Wrapped the destroy() call in runCatchingWithReport for safe execution and logging.

How Has This Been Tested?

To verify the fix, I navigated between SharedDecksActivity and DeckPicker 10 times consecutively.

Result:

API 34: Some leaks still persist, but these are attributed to the Context issue as discussed in the issue thread.
However, the specific leaks related to improper WebView teardown have been significantly mitigated.

API 35: leaks are fully resolved with this cleanup in place.

API 34

Image

API 35

Image

Learning (optional, can help others)

Confirmed that applying the SafeWebViewLayout.safeDestroy() pattern directly within an Activity's onDestroy() is an effective experimental approach to mitigate WebView-related memory leaks in AnkiDroid.

Checklist

Please, go through these checks before submitting the PR.

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

@largeblueberry
Copy link
Contributor Author

I've refactored the code to centralize the WebView destruction logic into a static method within 'SafeWebViewLayout.'
This avoids code duplication while ensuring 'SharedDecksActivity' also benefits from the safe destruction process as suggested. Thanks for the feedback!"

Copy link
Member

@BrayanDSO BrayanDSO left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to use SafeWebViewLayout in SharedDecksActivity, then call safeDestroy() there

@largeblueberry
Copy link
Contributor Author

"Following your suggestion, I replaced the standard WebView with com.ichi2.anki.workarounds.SafeWebViewLayout and updated the ViewBinding to resolve compilation errors.

However, when I ran the app and navigated from DeckPicker to SharedDecksActivity, the app crashed with the following error:

java.lang.IllegalStateException: SafeWebViewLayout must be used within a Fragment

It seems SafeWebViewLayout was designed specifically for Fragments (it calls findFragment() in onAttachedToWindow).
Since SharedDecksActivity is an Activity, using this layout directly causes an issue.

Given this constraint, do you think I should refactor SafeWebViewLayout to support Activities as well, or would it be better to stick with WebView for this specific case?"

SafeWebviewLayout is only for fragment

@david-allison david-allison added the Needs Author Reply Waiting for a reply from the original author label Jan 17, 2026
@largeblueberry
Copy link
Contributor Author

Thanks for the feedback, David! I've updated the code to address your suggestions:
Simplified the call site in SharedDecksActivity by using Kotlin's default parameters for the parent view.
Improved KDoc to focus on the "what" and "why" as suggested, and removed the unnecessary @JvmStatic.

Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy, thanks so much! One minor request

@david-allison david-allison added Needs Second Approval Has one approval, one more approval to merge squash-merge A squash & force push is required. The PR author may do this to speed up the merge process. and removed Needs Review Needs Author Reply Waiting for a reply from the original author labels Jan 19, 2026
@david-allison david-allison removed the squash-merge A squash & force push is required. The PR author may do this to speed up the merge process. label Jan 19, 2026
@david-allison
Copy link
Member

I have squash merged and force pushed this to make it easier to merge.

If there are review comments, I'm happy to take responsibility for them, since I force pushed

Cheers!

@BrayanDSO BrayanDSO added this pull request to the merge queue Jan 19, 2026
@BrayanDSO BrayanDSO added Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) and removed Needs Second Approval Has one approval, one more approval to merge labels Jan 19, 2026
Merged via the queue into ankidroid:main with commit 99aeccc Jan 20, 2026
15 checks passed
@github-actions github-actions bot removed the Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) label Jan 20, 2026
@github-actions github-actions bot added this to the 2.24 release milestone Jan 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memory leak in SharedDecksActivity (suspected WebView Context issue)

3 participants