Open pradipawasthi opened 6 years ago
A lot of my app users have same problem and I don't know what to do...
Maybe it's better to call commitAllowingStateLoss()
than commitNow()
.
问题解决了吗?我也遇到这个问题了
I still use version 0.9.5 ,in this version, there is no this issue.
Thanks, I let't delay 200 millisecond, then no problem, if has problem I'm attempt your method!
我fork了一份解决了这个问题,比楼上的延时处理更好 https://github.com/YougaKing/RxPermissions.git
好像没有0.9.5 这个版本的吧
我fork了一份解决了这个问题,比楼上的延时处理更好 https://github.com/YougaKing/RxPermissions.git
你是处理的哪里
我fork了一份解决了这个问题,比楼上的延时处理更好 https://github.com/YougaKing/RxPermissions.git
你是处理的哪里
fragment 创建时机问题,java.lang.IllegalStateException
Same problem here
i have this problem too
i have problem too
A detailed description of the problem and what you have to do is here. https://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
In general, the best way to avoid the exception in these cases is to simply avoid committing transactions in asynchronous callback methods all together. Google engineers seem to agree with this belief as well. According to this post on the Android Developers group, the Android team considers the major shifts in UI that can result from committing FragmentTransactions from within asynchronous callback methods to be bad for the user experience.
we have to do:
blockingSubscribe()
commitAllowingStateLoss()
@tim4dev disagree with your suggestions (but not with article). According to provided link
Use commitAllowingStateLoss() only as a last resort.
Good way of handling such situations will be dispose subscribtions to any org.reactivestreams.Publisher
(e.g. Obsevable, Flowable etc) in Activity/Fragment onStop()
.
And if we speak about what is the best we could do with it I think in general we just don't need commit fragments transactions after onSaveInstanceState()
was called.
We use a lot of Rx code in our projects and we've forgotten about described crashes since we started clear all related to screen subscribtions in onStop()
(but we used to do it in onDestroy()
untill SKD implementation of FragmentTransactions was changed).
@mrArtCore it's very good that you learned how to work with RxJava. But you can believe that none of us use calls after onSaveInstanceState, and yet the error appears. What exactly do you suggest?
@tim4dev Hey, I don't like your sarcasm. First of all I tried to help. It appears that not all of users of this library quite familiar with Rx. My suggestions:
Show only stacktrace - is nothing. It's very hard understand what's going on if you will be look for problem solving without viewing from different perspectives.
This is an open source project, remember ? Nobody get paid for that fix. And if you are interested in this fix - give some help, please. Describe problem correctly!
Possible duplicate of https://github.com/tbruyelle/RxPermissions/issues/132 and https://github.com/tbruyelle/RxPermissions/issues/125
so,will you change commitNow() to commitAllowingStateLoss()? @tbruyelle
Same problem. It is hard to reproduce and seems like a random error.
Show us your code. Thats all. Oh, and stacktrace. And example project will be super helpful
@mrArtCore This is one of the crash logs from Crashlytics.
hasRightPermission
is for getting whether a permission has been granted.
Fatal Exception: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source:10)
at android.support.v4.app.FragmentManagerImpl.ensureExecReady(Unknown Source:51)
at android.support.v4.app.FragmentManagerImpl.execSingleAction(Unknown Source:11)
at android.support.v4.app.BackStackRecord.commitNow(Unknown Source:6)
at com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment(Unknown Source:24)
at com.tbruyelle.rxpermissions2.RxPermissions.access$000(Unknown Source)
at com.tbruyelle.rxpermissions2.RxPermissions$1.get(Unknown Source:9)
at com.tbruyelle.rxpermissions2.RxPermissions$1.get(Unknown Source)
at com.tbruyelle.rxpermissions2.RxPermissions.isGranted(Unknown Source:8)
at com.testapp.TestActivity.hasRightPermission(Unknown Source:9)
at com.testapp.TestActivity.onCreateOptionsMenu(Unknown Source:37)
at android.app.Activity.onCreatePanelMenu(Activity.java:3567)
at android.support.v4.app.FragmentActivity.onCreatePanelMenu(Unknown Source:2)
at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(Unknown Source:2)
at android.support.v7.app.AppCompatDelegateImpl$AppCompatWindowCallback.onCreatePanelMenu(Unknown Source:8)
at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(Unknown Source:2)
at android.support.v7.app.ToolbarActionBar.populateOptionsMenu(Unknown Source:24)
at android.support.v7.app.ToolbarActionBar$1.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6981)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
Hi @stargt ! I see you have some testapp and just may be you are able to reproduce this crash ? And what's more important that is code how you request permissions. Could you share it ?
I meet the same Exception
@wangjiangtao Guys, how about to show code ? Did you check this and this comments ?
Read carefully please, and if this is doesn't solve your problems, give us yout code example.
我fork了一份解决了这个问题,比楼上的延时处理更好 https://github.com/YougaKing/RxPermissions.git
老哥,,,你的pull request 未被允许呀
我也是 不提供解决方案吗
0.10.2 still have this problem java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(SourceFile:2080) at android.support.v4.app.FragmentManagerImpl.ensureExecReady(SourceFile:2219) at android.support.v4.app.FragmentManagerImpl.execSingleAction(SourceFile:2239) at android.support.v4.app.BackStackRecord.commitNow(SourceFile:648) at com.tbruyelle.rxpermissions2.b.b(SourceFile:77) at com.tbruyelle.rxpermissions2.b.a(SourceFile:36) at com.tbruyelle.rxpermissions2.b$1.get(SourceFile:61) at com.tbruyelle.rxpermissions2.b$1.get(SourceFile:54) at com.tbruyelle.rxpermissions2.b.isGranted(SourceFile:308) at showPermission(SourceFile:25) at .onClick(SourceFile:332) at android.view.View.performClick(View.java:6324) at android.view.View$PerformClick.run(View.java:24977) at android.os.Handler.handleCallback(Handler.java:790) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:192) at android.app.ActivityThread.main(ActivityThread.java:6814) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:818)
This bug is also occasionally found on our side.
@zhuxiaohao @lkang08
Guys, if you provide code where such error could be reproduced (with "steps to reproduce" of course), I'll try to help. This crash affected many users, as I can see now... Guys, messages and stacktraces without code where bug could be represented worth nothing. Nobody want waste so much time here.
I've got idea why this crash appear (maybe it's about Permission emission without check for activeObservers) but I have no time to setup enviroment where crash could be reproduced.
Good luck!
I don't know what to do with rx methods and I can't create example that can reproduce this exception (I've spend whole evening in tryings and can't reproduce). But exception in rx methods will be emitted into downstream and easy to catch. More important that this exception can be thrown with isGranted
methos which isn't rx method. I think, for such non-rx methods creation of fragment can be replaced with ContextCompat.checkSelfPermission
methods.
@fAntel Your activity/fragment is not in 'right' state, I suppose. Maybe it happens when screen is rotated or something.
You can add check like lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
inside subscribe()
method. Or something like this.
Play around. It's hard to suggest something useful while having no idea what is going on in your code.
@mrArtCore if we look at stack traces above we can see this line
com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment
It create fragment inside library code. Even on non-rx methods like isGranted
. And I suggest to swap this with ContextCompat.checkSelfPermission
call inside library code.
As workaround I've already swaped all RxPermissions.isGranted
calls with ContextCompat.checkSelfPermission
in my app because error in rx pipeline will be consumed at onError
method in subscribe
but non-rx call RxPermission.isGranted
if called at main thread will lead to crash.
@fAntel Thanks for suggestion. Still trying to stick to the library. But don't understand why, for calling three functions, which already implemented in AppCompat.
Wow
在 activity 的oncreate的时候就先使用rxpermission 把RxPermissionsFragment 的实例初始化并与当前activity相绑定就行,因为在RxPermissions的getRxPermissionsFragment中会做判断,判断该RxPermissionsFragment是否被初始化
You can use try catch
,able to handle some scenarios.
@mrArtCore Sorry for trouble you, but please check my case: My steps is following: Load API -> request RxPermission -> Crash with same log:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at androidx.fragment.app.FragmentManager.checkStateLoss(FragmentManager.java:1703)
at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1806)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1826)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
at com.tbruyelle.rxpermissions3.RxPermissions.getRxPermissionsFragment(RxPermissions.java:78)
at com.tbruyelle.rxpermissions3.RxPermissions.access$000(RxPermissions.java:37)
at com.tbruyelle.rxpermissions3.RxPermissions$1.get(RxPermissions.java:62)
at com.tbruyelle.rxpermissions3.RxPermissions$1.get(RxPermissions.java:55)
at com.tbruyelle.rxpermissions3.RxPermissions.pending(RxPermissions.java:212)
at com.tbruyelle.rxpermissions3.RxPermissions.request(RxPermissions.java:201)
at com.tbruyelle.rxpermissions3.RxPermissions.access$100(RxPermissions.java:37)
at com.tbruyelle.rxpermissions3.RxPermissions$4.apply(RxPermissions.java:156)
at io.reactivex.rxjava3.core.Observable.compose(Observable.java:6765)
at com.tbruyelle.rxpermissions3.RxPermissions.requestEachCombined(RxPermissions.java:194)
My problem is when loading API -> user move app to background -> RxPermission called on background -> so crash happened!
So what should I do? Should I check if app is background and wait until app resume, then call RxPermisson?
Can not perform this action after onSaveInstanceState
com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment
how to solve it?
@mrArtCore Sorry for trouble you, but please check my case: My steps is following: Load API -> request RxPermission -> Crash with same log:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at androidx.fragment.app.FragmentManager.checkStateLoss(FragmentManager.java:1703) at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1806) at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1826) at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297) at com.tbruyelle.rxpermissions3.RxPermissions.getRxPermissionsFragment(RxPermissions.java:78) at com.tbruyelle.rxpermissions3.RxPermissions.access$000(RxPermissions.java:37) at com.tbruyelle.rxpermissions3.RxPermissions$1.get(RxPermissions.java:62) at com.tbruyelle.rxpermissions3.RxPermissions$1.get(RxPermissions.java:55) at com.tbruyelle.rxpermissions3.RxPermissions.pending(RxPermissions.java:212) at com.tbruyelle.rxpermissions3.RxPermissions.request(RxPermissions.java:201) at com.tbruyelle.rxpermissions3.RxPermissions.access$100(RxPermissions.java:37) at com.tbruyelle.rxpermissions3.RxPermissions$4.apply(RxPermissions.java:156) at io.reactivex.rxjava3.core.Observable.compose(Observable.java:6765) at com.tbruyelle.rxpermissions3.RxPermissions.requestEachCombined(RxPermissions.java:194)
My problem is when loading API -> user move app to background -> RxPermission called on background -> so crash happened!
So what should I do? Should I check if app is background and wait until app resume, then call RxPermisson?
have you solved it?
RxPermissions Class constructor creates a fragment; In order to commit the fragment transaction, the activity from which the fragment was supposed to be created must be in the foreground.
The onSaveInstanceState method is called right before the onStop method. If a fragment transaction is committed after onSaveInstanceState, Error Cannot perform this action
will be thrown.
Solution:
androidx.lifecycle
library.if (this?.lifecycle?.currentState?.isAtLeast(Lifecycle.State.RESUMED) == true)
new RxPermissions(activity)
Alternatively, we can use a boolean to keep track of activity lifecycles if the androidx.lifecycle library is not added in your project!
Try unsubscribe from the stream whenever the state is saved -> onSaveInstanceState
is called. I suggest you do it in fragment/activity#onStop()
callback and you will be good to go.
09-15 13:31:03.381 15829-15829/com.doubtnutapp W/System.err: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at androidx.fragment.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2091) at androidx.fragment.app.FragmentManagerImpl.ensureExecReady(FragmentManager.java:2229) at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2249) at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:648) 09-15 13:31:03.382 15829-15829/com.doubtnutapp W/System.err: at com.tbruyelle.rxpermissions2.RxPermissions.getRxPermissionsFragment(RxPermissions.java:77) at com.tbruyelle.rxpermissions2.RxPermissions.access$000(RxPermissions.java:36) at com.tbruyelle.rxpermissions2.RxPermissions$1.get(RxPermissions.java:61) at com.tbruyelle.rxpermissions2.RxPermissions$1.get(RxPermissions.java:54) at com.tbruyelle.rxpermissions2.RxPermissions.pending(RxPermissions.java:211) at com.tbruyelle.rxpermissions2.RxPermissions.request(RxPermissions.java:200) at com.tbruyelle.rxpermissions2.RxPermissions.access$100(RxPermissions.java:36) at com.tbruyelle.rxpermissions2.RxPermissions$2.apply(RxPermissions.java:102) at io.reactivex.Observable.compose(Observable.java:6283) at com.tbruyelle.rxpermissions2.RxPermissions.request(RxPermissions.java:176) at com.doubtnutapp.ui.splash.SplashActivity.requestPermission(SplashActivity.kt:143) at com.doubtnutapp.ui.splash.SplashActivity$onStart$1.onInitFinished(SplashActivity.kt:131) at io.branch.referral.ServerRequestRegisterInstall.onRequestSucceeded(ServerRequestRegisterInstall.java:106) at io.branch.referral.Branch$BranchPostTask.onPostExecute(Branch.java:2937) at io.branch.referral.Branch$BranchPostTask.onPostExecute(Branch.java:2799) at android.os.AsyncTask.finish(AsyncTask.java:660) at android.os.AsyncTask.-wrap1(AsyncTask.java) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:677) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:165) at android.app.ActivityThread.main(ActivityThread.java:6365) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:883) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)