You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I noticed this issue when testing an app that uses fragments to set the toolbar.
MyFragment.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// This causes the activity's window callback to be reset to `mAppCompatWindowCallback`
(requireActivity() as AppCompatActivity).setSupportActionBar(toolbar)
}
The root cause can be seen in AppCompatDelegateImpl.
AppCompatDelegateImpl.java
@Override
public void setSupportActionBar(Toolbar toolbar) {
// Below the windowCallback is reset based on `mAppCompatWindowCallback` or some wrapped variant. Curtain's wrapper will be overridden.
if (toolbar != null) {
final ToolbarActionBar tbab = new ToolbarActionBar(toolbar, getTitle(),
mAppCompatWindowCallback);
mActionBar = tbab;
mWindow.setCallback(tbab.getWrappedWindowCallback());
} else {
mActionBar = null;
// Re-set the original window callback since we may have already set a Toolbar wrapper
mWindow.setCallback(mAppCompatWindowCallback);
}
invalidateOptionsMenu();
}
Longer explanation:
Setting a toolbar in Activitity.onCreate() is not an issue since mWindow.setCallback(...) above runs well before the ActivityThread goes through the process of adding a new view to the global window manager.
Curtains relies on modifications of mViews in the window manager via the spy delegator list. If setSupportActionBar runs after the view is added to the window manager, Curtains can't attach its window callback. Curtains would have to wait until addView is called again (which is not the case for fragments).
Possible workarounds
Modify mAppCompatWindowCallback to be the Curtains callback wrapper, such that any subsequent setSupportActionBar() call retains the Curtains window callback.
In WindowCallbackWrapper.Companion add something to check if the callback is the Curtain's variant (or just invoke Window.listeners which does this refresh itself). Now the question is, when to best invoke this - perhaps from a fragment lifecycle listener via onFragmentStarted?
fun Window.reapplyWindowCallbackWrapper(): Boolean {
synchronized(listenersLock) {
if (this.callback is WindowCallbackWrapper) return false
val wrapperToApply = callbackCache[this]?.get() ?: WindowCallbackWrapper(this.callback)
this.callback = wrapperToApply
callbackCache[this] = WeakReference(wrapperToApply)
return true
}
}
The text was updated successfully, but these errors were encountered:
I noticed this issue when testing an app that uses fragments to set the toolbar.
The root cause can be seen in
AppCompatDelegateImpl
.Longer explanation:
Setting a toolbar in
Activitity.onCreate()
is not an issue sincemWindow.setCallback(...)
above runs well before theActivityThread
goes through the process of adding a new view to the global window manager.Curtains relies on modifications of
mViews
in the window manager via the spy delegator list. IfsetSupportActionBar
runs after the view is added to the window manager, Curtains can't attach its window callback. Curtains would have to wait until addView is called again (which is not the case for fragments).Possible workarounds
Modify
mAppCompatWindowCallback
to be the Curtains callback wrapper, such that any subsequentsetSupportActionBar()
call retains the Curtains window callback.In
WindowCallbackWrapper.Companion
add something to check if the callback is the Curtain's variant (or just invoke Window.listeners which does this refresh itself). Now the question is, when to best invoke this - perhaps from a fragment lifecycle listener viaonFragmentStarted
?The text was updated successfully, but these errors were encountered: