Closed mbarta closed 5 years ago
I discussed with Adam Powell some time ago, the method isInBackStack()
should actually become public.
stops working after migrating to AndroidX due to the change of package names.
that is true unfortunately but there is no easy way around this. The plan is the following: Once androidx
is a stable release I will pump version of Mosby to Mosby 4.0 and Mosby 4 will be compatible with androidx
only. Open to discuss this and happy for any feedback.
As a temporary workaround until then for those who want to continue using AndroidX, you can exclude the utils-fragment
module dependency in your build.gradle
:
compile 'com.hannesdorfmann.mosby3:mvi:3.1.0' {
exclude group: 'com.hannesdorfmann.mosby3', module: 'utils-fragment'
}
and then define your own androidx.core.app.BackstackAccessor
class:
package androidx.core.app;
import androidx.fragment.app.Fragment;
public class BackstackAccessor {
public static boolean isFragmentOnBackStack(Fragment fragment) {
return false;
}
}
AndroidX is now stable 1.0.0. Even more, Google wrote that the Support 28.0.0 is the last version that supports android.support
package. It is time to move on.
@sockeqwe Hannes, does this affect users of Mosby with Conductor? I guess it'll not since Conductor handles its own backstack and lifecycle which Mosby makes use of it, but I'll soon enough have to migrate to AndroidX for a mammoth of a project and don't want this to be an issue 😕
I have to double check it but Conductor should not be a problem. It doesn't use BackstackAccessor
at all.
@sockeqwe Would you consider using this workaround in mosby:
public static boolean isInBackStack(final Fragment fragment) {
try {
return fragment.isInBackStack();
} catch (IllegalAccessError e) {
return isInBackStackAndroidX(fragment);
}
}
/**
* Hacky workaround because Fragment#isInBackStack is inaccessible with AndroidX
*/
private static boolean isInBackStackAndroidX(final Fragment fragment) {
final StringWriter writer = new StringWriter();
fragment.dump("", null, new PrintWriter(writer), null);
final String dump = writer.toString();
return !dump.contains("mBackStackNesting=0");
}
Another possible solution is to keep current implementation and introduce a BackStackAccessorProvider
which will let users use a different logic for determining if a fragment is in the back stack or not.
Yes
Guy Carmeli notifications@github.com schrieb am Fr., 26. Okt. 2018, 17:05:
@sockeqwe https://github.com/sockeqwe Would you consider using this workaround https://github.com/grandcentrix/ThirtyInch/commit/05aa2c6ac8eee520e8b0da2bf84b6ce8b79d94bd#diff-4b8d82f65d5fc975ee47d3ccd24b41de in mosby:
public static boolean isInBackStack(final Fragment fragment) { try { return fragment.isInBackStack(); } catch (IllegalAccessError e) { return isInBackStackAndroidX(fragment); } } /** Hacky workaround because Fragment#isInBackStack is inaccessible with AndroidX/private static boolean isInBackStackAndroidX(final Fragment fragment) { final StringWriter writer = new StringWriter(); fragment.dump("", null, new PrintWriter(writer), null); final String dump = writer.toString(); return !dump.contains("mBackStackNesting=0"); }
Another possible solution is to keep current implementation and introduce a BackStackAccessorProvider which will let users use a different logic for determining if a fragment is in the back stack or not.
— You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/sockeqwe/mosby/issues/318#issuecomment-433439830, or mute the thread https://github.com/notifications/unsubscribe-auth/AAjnrvkI3qj3HQiKFoKFhtUsEsmMIavlks5uoyTRgaJpZM4VDp2H .
Thanks @sockeqwe, submitted a pr.
Edit 1: submitted a new pr
Edit 2: I published my fork which is compatible with AndroidX on jitpack. If anyone is interested you can use it until the PR is merged: implementation 'com.github.guyca:mosby:3.1.6'
Thabks a lot. I m going to publish a new release at the end of this week containing this. This makes it useable with jetifier. However I plan to make a 4.0 release that is fully backed on androidx soon (3.x sticks with old support library)
@sockeqwe When do you plan to release 3.1.1?
This evening, everything is ready on my side, just wanted to setup CI properly to release it from ci but that didn't work. Will release it manually.
Maxim Pestryakov notifications@github.com schrieb am Di., 6. Nov. 2018, 09:05:
@sockeqwe https://github.com/sockeqwe When do you plan to release 3.1.1?
— You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/sockeqwe/mosby/issues/318#issuecomment-436164248, or mute the thread https://github.com/notifications/unsubscribe-auth/AAjnrooykfXWuumOk_dMe4oqI2oLr1RVks5usULVgaJpZM4VDp2H .
@sockeqwe still no new release version ((
I have some problems with gradle uploading files of 3.1.1 release to different locations instead of just one single location. I asked that question on stackoverflow, if someone knows how to fix it, here is the link to stackoverflow: https://stackoverflow.com/questions/53200255/gradle-uploadarchives-runs-in-parallel-causing-multiple-staging-repositories-on
Meanwhile I have at least published a new 3.1.1-SNAPSHOT containing this stuf or you can use jitpack
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.sockeqwe:mosby:345efbb0c0'
}
I've read and responded to Your SO issue. TLDR; make sure You have no org.gradle.parallel=true
in your project root gradle.properties
file. Based on Your local Gradle configuration, using command line parameter to disable above mentioned paralellism might not work properly. It is worth to give a try.
Thanks for answering, I have that set, doesn't help unfortunately. Will try it on a different machine over the weekend.
Im still waiting
I appologize for the inconveniences. In the meantime you can use 3.1.1-SNAPSHOT
See Readme
Dmitry Ivanov notifications@github.com schrieb am So., 11. Nov. 2018, 09:59:
Im still waiting
— You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/sockeqwe/mosby/issues/318#issuecomment-437653807, or mute the thread https://github.com/notifications/unsubscribe-auth/AAjnruZZp3-dxHALS-VBQsDIfZn35mtFks5ut-b5gaJpZM4VDp2H .
Unfortunately, the build fails with this exception, because of duplicate BackstackAccessor.
Warning: Exception while processing task java.io.IOException:
Can't write [/home/me/projects/myappAndroid/myapp/build/intermediates/transforms/proguard/prodmyapp/release/0.jar]
(Can't read [/home/me/projects/myappAndroid/myapp/build/intermediates/transforms/RealmTransformer/prodmyapp/release/0(;;;;;;;**.class)]
(Can't read [androidx]
(Can't read [core]
(Can't read [app]
(Can't read [BackstackAccessor.class]
(Duplicate jar entry [androidx/core/app/c.class]))))))
Looking forward to this issue solved. I'm getting the same issue.
java.lang.IllegalAccessError: Method 'boolean androidx.fragment.app.Fragment.isInBackStack()' is inaccessible to class 'androidx.core.app.BackstackAccessor'
Yes error similar to @Jeff11 persists in 3.1.1-SNAPSHOT version using gradle dependency 'Program type already present: androidx.core.app.BackstackAccessor'
I just released 3.1.1
(not snapshot)
@LukasStancikas is your code available somewhere to reproduce this issue? I guess jetifier is doing to much "smart" things ending up having BackstackAccessor
somehow twice ... Do you use Mosby in app and in a library that uses Mosby as well?
In our AndroidX-enabled app the 3.1.1 does not work out of the box, BackstackAccessor
crashes with NoSuchMethodError
and not with IllegalAccessError
as handled in the code. The configuration I was testing has proguard optimizations enabled so it might be part of the issue here.
My workaround:
BackstackAccessor
fork and utils-fragment
exclusions as in https://github.com/sockeqwe/mosby/issues/318#issuecomment-403536460 above utils-fragment
but just call the isInBackStackAndroidX()
hack directlyI believe this could be fixed in the library by catching NoSuchMethodError
as well.
Hello @sockeqwe !
BackstackAccessor
used for checking that we should persist presenter on screen rotation because isRemoving == true
for fragments inside backstack on screen rotation. Right?
But we can check it other way: android calls onSaveInstanceState
for this fragments before screen rotation.
abstract class BaseFragment : AppCompatFragment() {
private var instanceStateSaved: Boolean = false
//This is android, baby!
private fun isRealRemoving(): Boolean =
(isRemoving && !instanceStateSaved) //because isRemoving == true for fragment in backstack on screen rotation
|| ((parentFragment as? BaseFragment)?.isRealRemoving() ?: false)
//It will be valid only for 'onDestroy()' method
private fun needDestroyPresenter(): Boolean =
when {
activity?.isChangingConfigurations == true -> false
activity?.isFinishing == true -> true
else -> isRealRemoving()
}
override fun onResume() {
super.onResume()
instanceStateSaved = false
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
instanceStateSaved = true
}
override fun onDestroy() {
super.onDestroy()
if (needDestroyPresenter()) {
//destroy presenter
}
}
}
I think @guyca code is dirty hack :wink:
Thank for compile 'com.hannesdorfmann.mosby3:mvp:3.1.1' // Plain MVP Issue was resolved for me.
With androidx.fragment 1.2.0 the @guyca dump()
hack does not work anymore. There's a bug in FragmentManager
trying to dump a detached fragment. Reported it as https://issuetracker.google.com/issues/148189412
As a workaround, changed the hack to another, reflection-based one:
private static boolean isInBackStackAndroidX120(final Fragment fragment) {
try {
Field backStackNestingField = Fragment.class.getDeclaredField("mBackStackNesting");
backStackNestingField.setAccessible(true);
int backStackNesting = backStackNestingField.getInt(fragment);
return backStackNesting > 0;
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
After updating the support library of my project to the new AndroidX scheme, the app started crashing after calling this method:
BackstackAccessor.isFragmentOnBackStack(Fragment())
Crash:java.lang.IllegalAccessError: Method 'boolean androidx.fragment.app.Fragment.isInBackStack()' is inaccessible to class 'androidx.core.app.BackstackAccessor'
After some investigation, I found that the issue is this file: https://github.com/sockeqwe/mosby/blob/master/utils-fragment/src/main/java/android/support/v4/app/BackstackAccessor.java which is accessing a non-public field by "faking" the package.
As well as being a bad practice, this stops working after migrating to AndroidX due to the change of package names.
Ideally this should be reverted to the commented-out version of the code still existing in the linked file.