Fixed
Status Update
Comments
he...@gmail.com <he...@gmail.com> #2
Definitely want to support this. Currently investigating moving the Callbacks to interfaces so that wrapping/conversion can be done:
private abstract class WrapperDataSource<in A, B>(private val source: PositionalDataSource<A>)
: PositionalDataSource<B>() {
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<B>) {
source.loadInitial(params, object: LoadInitialCallback<A> {
override fun onResult(data: List<A>, position: Int, totalCount: Int) {
callback.onResult(convert(data), position, totalCount)
}
override fun onResult(data: List<A>, position: Int) {
callback.onResult(convert(data), position)
}
})
}
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<B>) {
source.loadRange(params) { data -> callback.onResult(convert(data)) }
}
protected abstract fun convert(source: List<A>): List<B>
}
Making them interfaces makes it easy to wrap/test. Downside is that external callers can't use some of the guts of the callback impl (like validating non-negative positions), but this should make it much more reasonable to wrap, decorate, or otherwise post-process data loaded from e.g. Room. In the network case, the equivalent might be post-processing a network request in a way that's awkward to inject into network loading code.
private abstract class WrapperDataSource<in A, B>(private val source: PositionalDataSource<A>)
: PositionalDataSource<B>() {
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<B>) {
source.loadInitial(params, object: LoadInitialCallback<A> {
override fun onResult(data: List<A>, position: Int, totalCount: Int) {
callback.onResult(convert(data), position, totalCount)
}
override fun onResult(data: List<A>, position: Int) {
callback.onResult(convert(data), position)
}
})
}
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<B>) {
source.loadRange(params) { data -> callback.onResult(convert(data)) }
}
protected abstract fun convert(source: List<A>): List<B>
}
Making them interfaces makes it easy to wrap/test. Downside is that external callers can't use some of the guts of the callback impl (like validating non-negative positions), but this should make it much more reasonable to wrap, decorate, or otherwise post-process data loaded from e.g. Room. In the network case, the equivalent might be post-processing a network request in a way that's awkward to inject into network loading code.
ad...@google.com <ad...@google.com>
ad...@google.com <ad...@google.com> #3
Fixed internally by making Params constructors public, and Callbacks abstract. Will go out with next alpha release.
We're also investigating making it easier to wrap and do decoration/type conversions, since the example in #2 mostly works, but is incomplete - it needs to handle invalidates.
We're also investigating making it easier to wrap and do decoration/type conversions, since the example in #2 mostly works, but is incomplete - it needs to handle invalidates.
he...@gmail.com <he...@gmail.com> #5
@4 That actually won't technically fix as isHidden() will technically mismatch with the state passed into the child fragment. Each child fragment legitimately needs to have their state set to hidden.
al...@gmail.com <al...@gmail.com> #6
Yeah, I realized that as I kept working further on it. Nevermind that solution, it doesn't work.
he...@gmail.com <he...@gmail.com> #7
@6 I don't know what the ramifications are, but when you iterate, you can save the "currentState" and then hide them all via a transaction. When restoring to visible, restore to the original state.
il...@google.com <il...@google.com>
il...@google.com <il...@google.com>
ap...@google.com <ap...@google.com> #8
Project: platform/frameworks/support
Branch: androidx-main
commit 02290cddca3d5e4dc94e2c5f77a6728ad970b204
Author: Jeremy Woods <jbwoods@google.com>
Date: Thu Oct 07 13:11:45 2021
Dispatch onHiddenChanged to child fragments
When a parent fragment is hidden all of its children will automatically
be hidden, but we never call onHiddenChanged on any of the children.
We should dispatch onHiddenChanged down parent's entire hierarchy and
ensure that `isHidden()` also considers the parent's state.
RelNote: "Parent fragments will now dispatch `onHiddenChanged()` down
their entire hierarchy before launching their own call back."
Test: added test
Bug: 77504618
Change-Id: Iedc201ab435cb963e81bc02d203d4d37ff827e01
M fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
https://android-review.googlesource.com/1850016
Branch: androidx-main
commit 02290cddca3d5e4dc94e2c5f77a6728ad970b204
Author: Jeremy Woods <jbwoods@google.com>
Date: Thu Oct 07 13:11:45 2021
Dispatch onHiddenChanged to child fragments
When a parent fragment is hidden all of its children will automatically
be hidden, but we never call onHiddenChanged on any of the children.
We should dispatch onHiddenChanged down parent's entire hierarchy and
ensure that `isHidden()` also considers the parent's state.
RelNote: "Parent fragments will now dispatch `onHiddenChanged()` down
their entire hierarchy before launching their own call back."
Test: added test
Bug: 77504618
Change-Id: Iedc201ab435cb963e81bc02d203d4d37ff827e01
M fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
M fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
jb...@google.com <jb...@google.com> #9
This has been fixed internally and will be available in the Fragment 1.4.0-beta01
release.
Description
2) hide fragment (A)
a) onHiddenChanged() gets called for (A)
b) onHiddenChanged() does not get called for (B)
My expectation would be if the fragment itself is hidden, it's children would also be constituted as hidden. A general workaround would be to never rely on a Fragment's hidden state since if you made your fragment correctly, you wouldn't need to worry about the context in which the fragment is being used (either in a child fragment manager or not). The fact that you have to rely no the context in which the fragment is used makes onHiddenChanged() and isHidden() in most cases useless. This means we are left having to add a OnGlobalLayoutChangeListener and listen for whether the root view of the fragment is visible or not.