Status Update
Comments
vs...@google.com <vs...@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.
an...@cabmaster.com <an...@cabmaster.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?
vs...@google.com <vs...@google.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.
ap...@googlemail.com <ap...@googlemail.com> #5
Thanks, yep, I was able to reproduce it.
aa...@gmail.com <aa...@gmail.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.
[Deleted User] <[Deleted User]> #7
Are you referring to the first `onStop` that happens right after unlock (line 12 in screenshot)?
lo...@gmail.com <lo...@gmail.com> #8
yep
al...@gmail.com <al...@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.
vs...@google.com <vs...@google.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()
th...@gmail.com <th...@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")
}
}
[Deleted User] <[Deleted User]> #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!")
}
}
vs...@google.com <vs...@google.com> #13
It's happening also after entering to multi-window mode
wi...@gmail.com <wi...@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.
[Deleted User] <[Deleted User]> #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:
[Deleted User] <[Deleted User]> #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.
wi...@gmail.com <wi...@gmail.com> #17
This is fixed internally and will be available in future releases of the fragment dependency.
vs...@google.com <vs...@google.com> #18
when and which version will this fix be included?
wi...@gmail.com <wi...@gmail.com> #19
The fix is available in 28.0.0-alpha3 and AndroidX 1.0.0-alpha3
sn...@gmail.com <sn...@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.
em...@gmail.com <em...@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
ka...@gmail.com <ka...@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.
ro...@gmail.com <ro...@gmail.com> #25
Raising targetSdk is not needed. Only compileSdk needs to be raised to be able to use support lib 28
ma...@gmail.com <ma...@gmail.com> #26
Right, sorry about that. Realized this soon after but couldn’t edit the response :(
ma...@gmail.com <ma...@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!
sm...@gmail.com <sm...@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.
oa...@gmail.com <oa...@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.
am...@gmail.com <am...@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.
Description
Build #AI-135.1653844
Upon Debugging an application there is an issue where you can get to a point where Android Studio just says "Waiting until last debugger command completes" ...
There is no easy way to replicate this, but I can try and explain what I did the best I can...
Start to debug the apk
make the code hit a breakpoint
step over the code several times
after an unknown number of times you will no longer be able to debug the app, but in the variables section you will have "Waiting until last debugger command completes"
Android Studio does NOT crash it is still use-able, i can move around, write code and do everything (exclude debug)
Restarting Android Studio doesn't help
Restarting the PC doesn't help
Rebooting the phone doesn't help
I have yet to try:
Using another phone
Re-installing Android Studio
I will try using another phone today to see if that helps...
It never used to do this before so it could be project related. i can't upload the project publicly due to privacy concerns and the size of the project, but if a Google Employee wants the project, then feel free to ask and I will send it to them privately.