Status Update
Comments
ap...@google.com <ap...@google.com> #2
Branch: androidx-main
commit 57ca221882695bd6a52549f4d9ea3b812e6fe87c
Author: Simon Schiller <simonschiller@users.noreply.github.com>
Date: Mon Mar 22 16:09:30 2021
[GH] [FragmentStrictMode] Detect <fragment> tag usage
## Proposed Changes
- Detect `<fragment>` tag usage inside XML layouts
## Testing
Test: See `FragmentStrictModeTest#detectFragmentTagUsage`
## Issues Fixed
Fixes: 153738235
This is an imported pull request from
Resolves #141
Github-Pr-Head-Sha: 4ea052596e4341b9f11bcf335e2bc38045a91f19
GitOrigin-RevId: 62e7487aa4874eef6bb556490e193717cf937251
Change-Id: Iae48578e85e4e4897f806d7ade2e2a660adf9479
M fragment/fragment/api/public_plus_experimental_current.txt
M fragment/fragment/api/restricted_current.txt
M fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentLayoutInflaterFactory.java
M fragment/fragment/src/main/java/androidx/fragment/app/strictmode/FragmentStrictMode.java
A fragment/fragment/src/main/java/androidx/fragment/app/strictmode/FragmentTagUsageViolation.java
ap...@google.com <ap...@google.com> #3
Branch: androidx-master-dev
commit 8bd7049d70a5f9a753f55708b90b9a6a05aaa8c6
Author: Jeremy Woods <jbwoods@google.com>
Date: Wed Apr 01 17:33:55 2020
Add Fragment kotlin extentions for setResult
The initial APIs for setting fragment results were on the
FragmentManager. It would be nice if developers could also set and
listen for their results through APIs on Fragment.
This change adds kotlin extension methods that handle results directly
from the fragmentManager.
Test: FragmentTest.kt
Bug: 149787344
Change-Id: Ife12f84629633fb373355b2be612ebb021ae3781
M fragment/fragment-ktx/api/1.3.0-alpha04.txt
M fragment/fragment-ktx/api/current.txt
M fragment/fragment-ktx/api/public_plus_experimental_1.3.0-alpha04.txt
M fragment/fragment-ktx/api/public_plus_experimental_current.txt
M fragment/fragment-ktx/api/restricted_1.3.0-alpha04.txt
M fragment/fragment-ktx/api/restricted_current.txt
M fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentResultOwnerTest.kt
A fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentTest.kt
A fragment/fragment-ktx/src/main/java/androidx/fragment/app/Fragment.kt
ap...@google.com <ap...@google.com> #4
Branch: androidx-master-dev
commit 6f8597eca9e4d6f12c0b9bdb82b63f9153fb6123
Author: Jeremy Woods <jbwoods@google.com>
Date: Thu Apr 02 16:12:19 2020
Deprecate target fragment APIs
Now that we have the fragment result APIs (aosp/1273623) we should
encourage developers to use those instead of target fragments. Using
target fragments requires accessing the instance of another fragment and
the state of the fragment being accessed is unpredictable. Target
fragment also only allows for communication between sibling fragments
(those in the same fragment manager).
The new fragment result APIs do not have these issues. The results are
handled by the fragment manager and you can set and listen for results
anywhere in the fragment hierarchy (to/from parent and child fragments).
Test: ./gradlew bOS
Bug: 149787344
RelNote: "The target fragment APIs have been deprecated. To pass
data between fragments the new FragmentResult APIs should be used
instead."
Change-Id: I372f0ec92cf3712e206e26425a92a79467ee99b9
M fragment/fragment/api/1.3.0-alpha04.txt
M fragment/fragment/api/current.txt
M fragment/fragment/api/public_plus_experimental_1.3.0-alpha04.txt
M fragment/fragment/api/public_plus_experimental_current.txt
M fragment/fragment/api/restricted_1.3.0-alpha04.txt
M fragment/fragment/api/restricted_current.txt
M fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitionTest.kt
M fragment/fragment/src/androidTest/java/androidx/fragment/app/TargetFragmentLifeCycleTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
jb...@google.com <jb...@google.com> #5
This has been fixed internally and will be available in the Fragment 1.3.0-alpha04
release.
With this change, using a fragment manager, you can now pass a result between two fragments.
If Fragment A
needs a result from Fragment B
..
A
should call setResultListener()
:
var result : String? = null
@Override
void onCreate() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setResultListener("requestKey") { key, bundle ->
result = bundle.getString("bundleKey")
// Do something with the result..
}
}
}
B
should call setResult()
with the same key as the listener in A
button("Send result button") {
val result = "result"
setResult("requestKey", bundleOf("bundleKey" to result))
}
Fragment A
will receive the result and execute its callback once it is STARTED.
de...@gmail.com <de...@gmail.com> #6
Hello . I try to setResultListener from fragment A and Fragment B (A to B and back to A) and return result from FragmentDialog C. Use same request key for fragment A and B. On first load screen A - listener work fine, but when i go to screen B and then return on screen A - listener on fragment A dont work anymore.
Fragment A and fragment B set listeners on onViewCreated callback
val result =
bundle.getBoolean(RegularPayAgreementDialog.REGULAR_PAY_AGREEMENT_BUNDLE_KEY)
if (result) {
viewModel.onAgreementAccepted()
}
}
And set result on DialogFragment
setFragmentResult(
REGULAR_PAY_AGREEMENT_REQUEST_KEY,
bundleOf(REGULAR_PAY_AGREEMENT_BUNDLE_KEY to true)
)
de...@gmail.com <de...@gmail.com> #7
The problem is when 2 fragments try setResultListener with one same result key(
jb...@google.com <jb...@google.com> #8
As stated in
The Fragment result listeners are not stored in the Fragment, it is actually stored in the FragmentManager. So adding another listener, with the same key for two Fragments with the same FragmentManager will overwrite the first listener.
b9...@gmail.com <b9...@gmail.com> #9
LifecycleEventObserver observer = new LifecycleEventObserver() {
if (event == Lifecycle.Event.ON_DESTROY) {
lifecycle.removeObserver(this); // only remove observer when onDestroy
mResultListeners.remove(requestKey);
}
}
};
lifecycle.addObserver(observer);
I think it would be better remove observer right after the callback is fired, sometimes we don't want the observer keep listening. In that way we could wrap the whole task in one block (like coroutine style), more flexible.
il...@google.com <il...@google.com> #10
Re #9 - you can certainly clear out your FragmentResultListener
after you receive a result if that's the behavior you want for your business logic. The clean up mentioned in your comment is only to prevent memory leaks and not for business logic purposes.
Description
We should add a clean way of passing results between two Fragments.
It should be able to properly handle process death and with it, we can deprecate target fragment.
Target fragment requires directly accessing the instance of another Fragment and not only is that discouraged, but the state of the Fragment being accessed is unpredictable so it is also dangerous. Target fragment is also not supported in Navigation.
Long term, the Fragment Lifecycle methods will be driven with a LifecycleObserver and target fragment cannot exist in that world.