Status Update
Comments
b9...@gmail.com <b9...@gmail.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
il...@google.com <il...@google.com> #3
If you're using Hilt, you can also use hiltNavGraphViewModel()
viewModel()
that works in all scenarios (using Fragment 1.3.2 or Fragment 1.3.3, using Navigation Compose or not).
b9...@gmail.com <b9...@gmail.com> #4
Thanks for this information. hiltNavGraphViewModel()
will fallback to viewModel()
if LocalViewModelStoreOwner
isn't NavBackStackEntry
.
il...@google.com <il...@google.com> #5
True, you'd need to explicitly pass the defaultViewModelProviderFactory
to viewModel()
to force using the Fragment's ViewModelProviderFactory.
jb...@google.com <jb...@google.com>
il...@google.com <il...@google.com> #6
So there's three important use cases that we need to support when using the ViewTreeViewModelStoreOwner
API and the ViewModelStoreOwner
provided by that object:
-
Creating and using a custom Factory tied to the Fragment's View SavedStateRegistry (this is very important for
AbstractSavedStateViewModelFactory
andSavedStateViewModelFactory
- this is what was fixed in Fragment 1.3.3 in and why theb/181577191 ViewTreeViewModelStoreOwner
API now must return the privateFragmentViewLifecycleOwner
class. -
Using the default factory. Right now,
FragmentViewLifecycleOwner
does not implementHasDefaultViewModelProviderFactory
and, thus, aNewInstanceFactory
is always used. This is ~never correct andFragmentViewLifecycleOwner
should implement that interface and mimic the logic ofFragment
'sgetDefaultViewModelProviderFactory()
to lazily create aSavedStateVieModelFactory
. -
Developers who override
getDefaultViewModelProviderFactory()
at theFragment
level (either directly or via Hilt). Due to limitations in the ViewModel APIs (which we hope to address longer term), anyAbstractSavedStateViewModelFactory
factory here won't be using the rightSavedStateRegistry
as it should if used via theViewTreeViewModelStoreOwner
APIs (it'll be using theSavedStateRegistry
of the Fragment itself). However, this use case is quite important to have working out of the box and as it was before, despite not being exactly right.
These three cases must all work. Therefore, I think the best solution is to:
- Have
FragmentViewLifecycleOwner
implementHasDefaultViewModelProviderFactory
- Have that implementation call the Fragment's
getDefaultViewModelProviderFactory()
method. If that method returns a custom factory (i.e., not the one lazily created by Fragments when that method isn't overridden), use that factory. This will fix Hilt's use case. - If the factory returned by the Fragment's
getDefaultViewModelProviderFactory()
is the lazily created Fragment factory, instead create a new lazily createdSavedStateViewModelFactory
that is tied to theSavedStateRegistry
of the Fragment's View using the same logic as Fragment uses. This will fix the default factory case.
ap...@google.com <ap...@google.com> #7
Branch: androidx-main
commit 9732b80a90541d929a263f0e69e569818fbff839
Author: Sanura N'Jaka <sanura@google.com>
Date: Thu May 06 02:46:38 2021
Have FragmentViewLifecycleOwner implement HasDefaultViewModelProviderFactory
Making FragmentViewLifecycleOwner also implement
HasDefaultViewModelProviderFactory so that we either use the existing
custom factory or create a new SavedStateViewModelFactory that is tied
to the SavedStateRegistry of the Fragment's View and not the Fragment itself.
RelNote: "`FragmentViewLifecycleOwner` now implements
`HasDefaultViewModelProviderFactory` and overrides
`getDefaultViewModelProviderFactory()` so that we can
either use the existing custom factory or create a new
`SavedStateViewModelFactory` tied to the `SavedStateRegistry`
of the fragment's view."
Bug: 186097368
Test: ./gradlew checkApi
Change-Id: I5cbfacde2479fb270c0c344c478260f20b3207d5
A fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewLifecycleOwnerTest.kt
M fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
M fragment/fragment/src/main/java/androidx/fragment/app/FragmentViewLifecycleOwner.java
il...@google.com <il...@google.com> #8
We've fixed this issue for the upcoming Fragment 1.3.4 bug fix release and Fragment 1.4.0-alpha01.
When using Hilt or any fragment that overrides getDefaultViewModelProviderFactory()
, that factory will also be used from Compose's viewModel()
method.
Description
Fragment
setViewTreeViewModelStoreOwner
toFragmentViewLifecycleOwner
inFragmentViewLifecycleOwner
.FragmentViewLifecycleOwner
didn't implementHasDefaultViewModelProviderFactory
, so thatNewInstanceFactory
will be used to create ViewModel. Which means DI framework like Hilt will failed, the ViewModel constructor can't have any parameter.