Status Update
Comments
de...@whsoft.de <de...@whsoft.de> #2
Thanks for the detailed analysis and sample. I've prepared a CL, but I'd also be happy to review an external contribution since you already went through the trouble of identifying a fix. Just let me know here.
al...@google.com <al...@google.com>
ad...@gmail.com <ad...@gmail.com> #3
If you have a CL ready go for it.
That being said, I just went down git history and found when this was introduced:
As you can see, this was introduced to fix a "memory leak" though I don't quite understand why creating a new callback wrapper for every setSupportActionBar()
call is a problem.
se...@google.com <se...@google.com> #4
Branch: androidx-main
commit 200ccecbc8c7c5ba555e7fa15890edff67affb58
Author: Alan Viverette <alanv@google.com>
Date: Fri Apr 30 14:55:07 2021
Fix case where setSupportActionBar overwrites the window callback
RelNote: """Fix scenario where calling setSupportActionBar after setting the
window callback would overwrite the callback."""
Test: SupportActionBarTestCase
Fixes: 186791590
Change-Id: Ie43eedf8322caa44e7b201a95cbc64197953e020
A appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/SupportActionBarTestCase.kt
M appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
se...@google.com <se...@google.com> #5
ma...@gmail.com <ma...@gmail.com> #6
I vaguely remember this. The issue was iirc:
- You use multiple fragments (say switched via tabs). Each fragment calls
setSupportActionBar()
when visible. - The old code would wrap the current
Window.Callback
with something fromToolbarActionBar
(TAB), then set it as the window callback. - When the user switches to Tab #2, we'd do the same thing, but this time the callback wrapper chain would be
(((Root callback) TBAB1Wrapper) TBAB2Wrapper)
. TBAB1Wrapper would keep a reference a reference to the views even though the #1 fragment has likely been destroyed.
I've just +2'd Alan's CL, but the proper fix is properly to unwrap the callback from Window.getCallback()
.
ap...@google.com <ap...@google.com> #7
Let me uh... let me go back and properly fix that.
se...@google.com <se...@google.com> #8
One thing though, you can't quite unwrap because there's no guarantee you'll get the same callback (e.g. it might have been wrapped again).
It seems like what we want here is:
- ensure the callback is set at least once
- get a reference to it later
Is there a way the internal code can keep a ref to that new callback once its set, and reference it instead of installing or unwrap?
sa...@gmail.com <sa...@gmail.com> #9
there's no guarantee you'll get the same callback (e.g. it might have been wrapped again).
Do you mean the app code may have wrapped the callback?
se...@google.com <se...@google.com> #10
Yep. That's what got this issue filed after all ;-)
[Deleted User] <[Deleted User]> #11
Heh, of course.
Is there a way the internal code can keep a ref to that new callback once its set, and reference it instead of installing or unwrap?
This goes beyond my familiarity with (and available time to invest in understanding) the existing codebase -- I'd have to defer to Chris.
[Deleted User] <[Deleted User]> #12
I don't think there's a perfect solution here to be honest. I'm thinking that reverting to the previous solution is the only 'correct' way forward for the 80% case.
If apps want to change the window callback, they can override setSupportActionBar()
and do it in there, after calling super.
Description
Build: AI-203.7717.56.2031.7784292, 202110010236,
AI-203.7717.56.2031.7784292, JRE 11.0.10+0-b96-7249189x64 JetBrains s.r.o., OS Linux(amd64) v5.4.0-90-generic, screens 1920.0x1080.0
AS: Arctic Fox | 2020.3.1 Patch 3; Kotlin plugin: 203-1.6.0-release-798-AS7717.8; Android Gradle Plugin: 7.0.3; Gradle: 7.0.2; Gradle JDK: version 11.0.10; NDK: from local.properties: (not specified), latest from SDK: (not found); LLDB: pinned revision 3.1 not found, latest from SDK: (package not found); CMake: from local.properties: (not specified), latest from SDK: (not found), from PATH: 3.20.2
IMPORTANT: Please read