WAI
Status Update
Comments
am...@google.com <am...@google.com>
am...@google.com <am...@google.com> #2
After looking more into this issue, ViewModels are persisted using retained fragments. After adding retained fragments to the sample app, we can observe that retained fragments are not able to survive landscape lock and unlock scenario either.
ke...@gmail.com <ke...@gmail.com> #3
Hey, currently I can't reproduce your issue.
Link you provided doesn't work, in my simple test project I don't observe described issue.
Could you please say reupload your project somewhere else?
Could you please say what kind of lockscreen, do you use? (it may effect issue)
Could you reproduce this behavior on other devices?
Link you provided doesn't work, in my simple test project I don't observe described issue.
Could you please say reupload your project somewhere else?
Could you please say what kind of lockscreen, do you use? (it may effect issue)
Could you reproduce this behavior on other devices?
tl...@gmail.com <tl...@gmail.com> #4
Hey,
Sorry about the repo link, here is the public one:https://github.com/karmazindmitriy/viewmodelscoping , git@github.com:karmazindmitriy/viewmodelscoping.git
Tested on:
1. Device: NEXUS 5X, API level: 24, lock method: PIN / PATTERN / SWIPE / PASSWORD. Can reproduce by unlocking with any of the unlocking methods. Can also reproduce by unlocking with fingerprint.
2. Device: NEXUS 5X, API level: 27, lock method: PIN / PATTERN / PASSWORD . Can reproduce only when unlocking the device with a fingerprint. Unlocking with PIN / PATTERN / PASSWORD works fine.
3. Device: Pixel, API level: 27, lock method: PIN (haven't tested other) + fingerprint. Can reproduce only when unlocking the device with a fingerprint. Unlocking with PIN / PATTERN / PASSWORD works fine.
Hope this is helpful, please let me know if you need any other info.
Sorry about the repo link, here is the public one:
Tested on:
1. Device: NEXUS 5X, API level: 24, lock method: PIN / PATTERN / SWIPE / PASSWORD. Can reproduce by unlocking with any of the unlocking methods. Can also reproduce by unlocking with fingerprint.
2. Device: NEXUS 5X, API level: 27, lock method: PIN / PATTERN / PASSWORD . Can reproduce only when unlocking the device with a fingerprint. Unlocking with PIN / PATTERN / PASSWORD works fine.
3. Device: Pixel, API level: 27, lock method: PIN (haven't tested other) + fingerprint. Can reproduce only when unlocking the device with a fingerprint. Unlocking with PIN / PATTERN / PASSWORD works fine.
Hope this is helpful, please let me know if you need any other info.
ke...@gmail.com <ke...@gmail.com> #5
Thanks, yep, I was able to reproduce it.
nn...@google.com <nn...@google.com> #6
Oh, another instance when platform doesn't call onSaveInstanceState, but calls onStop and onRetainNonConfiguration, so fragments are confused, we are going to fix fragments so they work around this behavior.
tl...@gmail.com <tl...@gmail.com> #7
Are you referring to the first `onStop` that happens right after unlock (line 12 in screenshot)?
tl...@gmail.com <tl...@gmail.com> #8
yep
da...@gmail.com <da...@gmail.com> #9
Hello, I Have notice the same issue when using ViewModel, here is the scenario:
1) open ActivityA
-gets ViewModel with reference: TestViewModel@e71fab8
2) rotate device
-gets ViewModel with reference: TestViewModel@e71fab8
3) open ActivityB
4) rotate device
5) press back (finish Activity B)
6) Activity A comes back from stack
-gets ViewModel with reference: TestViewModel@260072e
I have tested with two kinds of ViewModel, with factory and default creation method:
ViewModelProviders.of(this).get(TestViewModel::class.java)
ViewModelProviders.of(this, factory).get(DashboardViewModel::class.java)
Both Activities extends AppCompatActivity class.
I have made some research and find case when this issue do not happend:
1) open ActivityA (vertical)
-gets ViewModel with reference: TestViewModel@e71fab8
2) rotate device (horizontal)
-gets ViewModel with reference: TestViewModel@e71fab8
3) open ActivityB (horizontal)
4) rotate device (vertical)
5) rotate device (horizontal)
6) press back (finish Activity B)
7) Activity A comes back from stack (horizontal)
-gets ViewModel with reference: TestViewModel@e71fab8
So when I rotate device twice on Activity B and press back the Activity A do not recreate ViewModel, mayeby it is becouse it has the same orientation as befor putting it in activities stack.
1) open ActivityA
-gets ViewModel with reference: TestViewModel@e71fab8
2) rotate device
-gets ViewModel with reference: TestViewModel@e71fab8
3) open ActivityB
4) rotate device
5) press back (finish Activity B)
6) Activity A comes back from stack
-gets ViewModel with reference: TestViewModel@260072e
I have tested with two kinds of ViewModel, with factory and default creation method:
ViewModelProviders.of(this).get(TestViewModel::class.java)
ViewModelProviders.of(this, factory).get(DashboardViewModel::class.java)
Both Activities extends AppCompatActivity class.
I have made some research and find case when this issue do not happend:
1) open ActivityA (vertical)
-gets ViewModel with reference: TestViewModel@e71fab8
2) rotate device (horizontal)
-gets ViewModel with reference: TestViewModel@e71fab8
3) open ActivityB (horizontal)
4) rotate device (vertical)
5) rotate device (horizontal)
6) press back (finish Activity B)
7) Activity A comes back from stack (horizontal)
-gets ViewModel with reference: TestViewModel@e71fab8
So when I rotate device twice on Activity B and press back the Activity A do not recreate ViewModel, mayeby it is becouse it has the same orientation as befor putting it in activities stack.
jr...@gmail.com <jr...@gmail.com> #10
This behavior is due to FragmentActivity.onDestroy() calling into mViewModelStore.clear() if mRetaining is false. This is the case when the device is rotated and the affected activity is in the background (and probably in other conditions outlined above as well). It is not the case if the configuration changes when the activity is in the front.
Since the view model store has ben cleared, a new view model will be created for the affected activity after a configuration change in the background.
The behavior can be observed easily using a break point in ViewModelStore.clear()
Since the view model store has ben cleared, a new view model will be created for the affected activity after a configuration change in the background.
The behavior can be observed easily using a break point in ViewModelStore.clear()
ba...@gmail.com <ba...@gmail.com> #11
Easy way to detect the condition from within onDestroy() on your own activity:
override fun onDestroy() {
val current = ViewModelProviders.of(this).get(VM::class.java)
super.onDestroy()
val fresh = ViewModelProviders.of(this).get(VM::class.java)
if (current != fresh) {
Log.e("Main", "View model has been destroyed")
}
}
override fun onDestroy() {
val current = ViewModelProviders.of(this).get(VM::class.java)
super.onDestroy()
val fresh = ViewModelProviders.of(this).get(VM::class.java)
if (current != fresh) {
Log.e("Main", "View model has been destroyed")
}
}
da...@gmail.com <da...@gmail.com> #12
And a dirty workaround:
override fun onDestroy() {
val current = ViewModelProviders.of(this).get(VM::class.java)
super.onDestroy()
@Suppress("UNCHECKED_CAST")
val fresh = ViewModelProviders.of(this, object : ViewModelProvider.Factory{
override fun <T : ViewModel?> create(modelClass: Class<T>) = current as T
}).get(VM::class.java)
if (current != fresh) {
Log.e("Main", "View model destroyed!")
}
}
override fun onDestroy() {
val current = ViewModelProviders.of(this).get(VM::class.java)
super.onDestroy()
@Suppress("UNCHECKED_CAST")
val fresh = ViewModelProviders.of(this, object : ViewModelProvider.Factory{
override fun <T : ViewModel?> create(modelClass: Class<T>) = current as T
}).get(VM::class.java)
if (current != fresh) {
Log.e("Main", "View model destroyed!")
}
}
ba...@gmail.com <ba...@gmail.com> #13
It's happening also after entering to multi-window mode
tl...@gmail.com <tl...@gmail.com> #14
Somebody put my issue https://issuetracker.google.com/issues/78095959 as a duplicate of this one. I would like to clarify, if this is really the case and if the issue that I reported will also be taken into account when fixing this issue.
Quote #6:
"Oh, another instance when platform doesn't call onSaveInstanceState, but calls onStop and onRetainNonConfiguration, so fragments are confused, we are going to fix fragments so they work around this behavior."
In the case which I presented, onSaveInstanceState IS called. But after that the activity is destroyed, so are the fragments. But ViewModel is not being cleared. There is a condition which skips clearing ViewModel after state is saved:
/**
* Called when the fragment is no longer in use. This is called
* after {@link #onStop()} and before {@link #onDetach()}.
*/
@CallSuper
public void onDestroy() {
mCalled = true;
// Use mStateSaved instead of isStateSaved() since we're past onStop()
if (mViewModelStore != null && !mHost.mFragmentManager.mStateSaved) {
mViewModelStore.clear();
}
}
But for fragments that are destroyed, loaders must be reset, like it happens in case of activity. I think the right condition for loader lifecycle to work correctly should be something like this:
if (mViewModelStore != null) {
// Do not reset loaders on activity rotation
final Activity activity = getActivity();
if (activity != null && !activity.isChangingConfigurations()) {
fragment.mViewModelStore.clear();
}
}
So loaders are always reset in Fragment.onDestroy(), unless the activity is rotated. I think this is also applicable to ViewModel.
Quote #6:
"Oh, another instance when platform doesn't call onSaveInstanceState, but calls onStop and onRetainNonConfiguration, so fragments are confused, we are going to fix fragments so they work around this behavior."
In the case which I presented, onSaveInstanceState IS called. But after that the activity is destroyed, so are the fragments. But ViewModel is not being cleared. There is a condition which skips clearing ViewModel after state is saved:
/**
* Called when the fragment is no longer in use. This is called
* after {@link #onStop()} and before {@link #onDetach()}.
*/
@CallSuper
public void onDestroy() {
mCalled = true;
// Use mStateSaved instead of isStateSaved() since we're past onStop()
if (mViewModelStore != null && !mHost.mFragmentManager.mStateSaved) {
mViewModelStore.clear();
}
}
But for fragments that are destroyed, loaders must be reset, like it happens in case of activity. I think the right condition for loader lifecycle to work correctly should be something like this:
if (mViewModelStore != null) {
// Do not reset loaders on activity rotation
final Activity activity = getActivity();
if (activity != null && !activity.isChangingConfigurations()) {
fragment.mViewModelStore.clear();
}
}
So loaders are always reset in Fragment.onDestroy(), unless the activity is rotated. I think this is also applicable to ViewModel.
da...@gmail.com <da...@gmail.com> #15
Was about to report this issue. I too am observing the same issue - exactly as do...@gmail.com https://issuetracker.google.com/issues/73644080#comment9 describes it. I also noted that if the ViewModel is instantiated with a Fragment - ie: mViewModel = ViewModelProviders.of(<Fragment>).get(TestViewModel.class); - the ViewModel will always get the same instance back - even in the above described scenarios.
I found a sample project on GitHub where the issue is easily reproduced as well:https://github.com/jshvarts/SimpleViewModel
I found a sample project on GitHub where the issue is easily reproduced as well:
da...@gmail.com <da...@gmail.com> #16
- I have a temporary solution that we have implemented using retained fragments to hold the ViewModel.
See:https://bitbucket.org/sajeevmadu/viewmodeltest for the solution.
See:https://issuetracker.google.com/issues/78788599
for a video of the issue.
See:
See:
for a video of the issue.
da...@gmail.com <da...@gmail.com> #17
This is fixed internally and will be available in future releases of the fragment dependency.
da...@gmail.com <da...@gmail.com> #18
when and which version will this fix be included?
ba...@gmail.com <ba...@gmail.com> #19
The fix is available in 28.0.0-alpha3 and AndroidX 1.0.0-alpha3
hn...@gmail.com <hn...@gmail.com> #22
For anyone still following this thread: tried with 28.0.0-alpha3 and AndroidX 1.0.0-alpha3 and it doesn't happen anymore.
ke...@gmail.com <ke...@gmail.com> #23
Sadly moving to AndroidX is a huge issue for large projects. It makes so many build errors. I hope it gets fixed in future version of Android Studio
ba...@gmail.com <ba...@gmail.com> #24
If you're comfortable with alpha releases of the support library, you can raise your target to 28 and use 28.0.0-alpha3.
ba...@gmail.com <ba...@gmail.com> #25
Raising targetSdk is not needed. Only compileSdk needs to be raised to be able to use support lib 28
on...@avast.com <on...@avast.com> #26
Right, sorry about that. Realized this soon after but couldn’t edit the response :(
ba...@gmail.com <ba...@gmail.com> #27
This issue is not fixed in 2.0.0-rc01. How can you consider calling this version release candidate with this bug!
jr...@gmail.com <jr...@gmail.com> #28
Supportlib 28 and AndroidX 2.0.0-rc01 releases are not related to navigation - navigation/workmanager are still in alpha in a separate release process. They have yet to release an androidx-package version, so they aren't included included in the initial 2.0 arch components release process. See https://developer.android.com/topic/libraries/architecture/adding-components#navigation - you need to update your navigation library version specifically.
ba...@gmail.com <ba...@gmail.com> #29
I faced the same issue after calling startActivityForResult and rotate screen and then return the resulting intent. I noticed that this also caused the onCleared() of the ViewModel to be invoked in the calling activity's viewmodel.
sy...@gmail.com <sy...@gmail.com> #30
Re #29, if you're still having an issue with 28.0.0-alpha3 or higher (or 1.0.0-alpha2 in AndroidX), please file a new issue with a sample project that reproduces your issue.
jr...@gmail.com <jr...@gmail.com> #31
Can anyone please make a sample project to test it out, and say what are the steps?
I think the issue was fixed, at least for loaders.
I think the issue was fixed, at least for loaders.
ma...@gmail.com <ma...@gmail.com> #32
"Retained fragments to hold the ViewModel" is not a reliable solution. After reverted some requested runtime permissions, such as Storage, Location and so on, retained ViewModel will be changed to a fresh one!
ar...@gmail.com <ar...@gmail.com> #33
I'm getting a similar issue. Multiple instances on my view model are being created on screen rotate. Here's a link to my repo: https://github.com/rahulchowdhury/elly/tree/add-elephant-profile
pa...@gmail.com <pa...@gmail.com> #34
Re #33 - you're unconditionally adding a new Fragment in your MainActivity, meaning you're adding a new instance for every rotation. You need to surround that code with if (savedInstanceState == null).
yo...@gmail.com <yo...@gmail.com> #35
Whoops. Totally missed that one out. Sorry. 😅
ta...@gmail.com <ta...@gmail.com> #36
@34 @35 Or check if the fragment exists, using findfragmentbytag .
cb...@gmail.com <cb...@gmail.com> #37
so much roundabout manipulation of how android works over the years is sad....
The way AppOps was withheld from end users until a bastardized version was cooked up that works make like an ultimatum type thing rather than simply denying permissions or feeding empty data.
...most of it reeks heavily of Google's data collection fetish and their opinion that we're all just stupid. The hostility towards user privacy and choice is so obvious it's not even funny.
The way AppOps was withheld from end users until a bastardized version was cooked up that works make like an ultimatum type thing rather than simply denying permissions or feeding empty data.
...most of it reeks heavily of Google's data collection fetish and their opinion that we're all just stupid. The hostility towards user privacy and choice is so obvious it's not even funny.
Description
/
/proc
/sys
In the case of the root (/) and /sys filesystems, a directory listing is not possible.
In the case of /proc, process data is only shown for the owning application process. That is, a query to /proc/{PID}/stat is only possible for the PID of the application performing the query.
The result of this restrictive behavior is that many system utility applications--including my own "SystemPanel" product--become entirely non-functional. Products such as these are popular with Play Store users because they can reveal applications that cause significant battery drain and provide awareness of applications/services running in the background.
I imagine this change was made with the intention of increased security, but the effect is that users are prevented from observing the behavior of their device through these system utility applications. This change can and will be used to the benefit of malware to remain hidden.
I am observing this on a Pixel C running Android N NPC56P (current version as of 30 March 2016). This report is based on observations of the device, I cannot find any documentation regarding the change.
Attached screenshot demonstrates the behavior. Left window is a file manager showing its version of the contents of /proc (retrieved using java.io.File API). Note that only one PID-numbered folder exists, corresponding to its own process. Right window is a terminal emulator, showing ls /, ls /sys commands failing. ls /proc shows only two numbered PID-folders, one for terminal emulator app process and one for its shell. Also shown is an attempt from terminal emulator to retrieve /proc/stat data about the process of the file manager (which fails).