Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

launchSingleTop属性跳转页面问题 #11

Open
hele-jeremy opened this issue Sep 16, 2021 · 3 comments
Open

launchSingleTop属性跳转页面问题 #11

hele-jeremy opened this issue Sep 16, 2021 · 3 comments
Labels

Comments

@hele-jeremy
Copy link



launchSingleTop属性跳转页面在不同的手机上有不同的 表现,某些手机会闪一下,某些机型会直接显示上一级的 页面

原因为hide隐藏的其实就是DFragment,而add添加的fragment其实也是Dfragment因此在同一个FragmentTransation中隐藏和添加同一个Fragment会有问题的,if (mBackStack.size() > 0 && mFragmentManager.getFragments().size() > 0) {
Log.d("Nav"," --Hide --Add");
ft.hide(mFragmentManager.getFragments().get(mBackStack.size() - 1));
ft.add(mContainerId, frag);
}
我修改了FragmentNavigator的navigate方法相当是launchsingletop的情况下,不将新创建的fragmet入栈:
public NavDestination navigate(@nonnull Destination destination, @nullable Bundle args,
@nullable NavOptions navOptions, @nullable Navigator.Extras navigatorExtras) {
if (mFragmentManager.isStateSaved()) {
Log.i(TAG, "Ignoring navigate() call: FragmentManager has already"
+ " saved its state");
return null;
}
String className = destination.getClassName();
if (className.charAt(0) == '.') {
className = mContext.getPackageName() + className;
}
final Fragment frag = instantiateFragment(mContext, mFragmentManager, className, args);
frag.setArguments(args);
final FragmentTransaction ft = mFragmentManager.beginTransaction();

    int enterAnim = navOptions != null ? navOptions.getEnterAnim() : -1;
    int exitAnim = navOptions != null ? navOptions.getExitAnim() : -1;
    int popEnterAnim = navOptions != null ? navOptions.getPopEnterAnim() : -1;
    int popExitAnim = navOptions != null ? navOptions.getPopExitAnim() : -1;
    if (enterAnim != -1 || exitAnim != -1 || popEnterAnim != -1 || popExitAnim != -1) {
        enterAnim = enterAnim != -1 ? enterAnim : 0;
        exitAnim = exitAnim != -1 ? exitAnim : 0;
        popEnterAnim = popEnterAnim != -1 ? popEnterAnim : 0;
        popExitAnim = popExitAnim != -1 ? popExitAnim : 0;
        ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim);
    }


    final @IdRes int destId = destination.getId();
    final boolean initialNavigation = mBackStack.isEmpty();
    // TODO Build first class singleTop behavior for fragments
    final boolean isSingleTopReplacement = navOptions != null && !initialNavigation
            && navOptions.shouldLaunchSingleTop()
            && mBackStack.peekLast() == destId;

    Log.d("testnav", " --isSingleTopReplacement --- " + isSingleTopReplacement);

    //TODO Tip 1: Solve the unexpected display of popUpToInclusive under the add hide solution
    //TODO Tip 2: Increase fault tolerance to deal with incorrectly-timed jumps in the case of nested sub-fragments
    Log.d("testnav", " --mBackStack.size:" + mBackStack.size()
            + " getFragments().size():" + mFragmentManager.getFragments().size());
    if (mBackStack.size() > 0 && mFragmentManager.getFragments().size() > 0) {
        Log.d("testnav", " --Add --- " + frag);
        Fragment hideFrag = mFragmentManager.getFragments().get(mBackStack.size() - 1);
        Log.d("testnav", " --Hide --- " + hideFrag);

        if (isSingleTopReplacement) {
            hideFrag.setArguments(args);
            ft.setMaxLifecycle(hideFrag, Lifecycle.State.RESUMED);
        } else {
            ft.hide(hideFrag);
            ft.add(mContainerId, frag);
            ft.setPrimaryNavigationFragment(frag);
        }

    } else {
        Log.d("testnav", " --Replace --- " + frag);
        ft.replace(mContainerId, frag);
        ft.setPrimaryNavigationFragment(frag);
    }

// ft.setPrimaryNavigationFragment(frag);

    boolean isAdded;
    if (initialNavigation) {
        isAdded = true;
    } else if (isSingleTopReplacement) {
        // Single Top means we only want one instance on the back stack

// if (mBackStack.size() > 1) {
// // If the Fragment to be replaced is on the FragmentManager's
// // back stack, a simple replace() isn't enough so we
// // remove it from the back stack and put our replacement
// // on the back stack in its place
// mFragmentManager.popBackStack(
// generateBackStackName(mBackStack.size(), mBackStack.peekLast()),
// FragmentManager.POP_BACK_STACK_INCLUSIVE);
// ft.addToBackStack(generateBackStackName(mBackStack.size(), destId));
// }
isAdded = false;
} else {
ft.addToBackStack(generateBackStackName(mBackStack.size() + 1, destId));
isAdded = true;
}
if (navigatorExtras instanceof Extras && !isSingleTopReplacement) {
Extras extras = (Extras) navigatorExtras;
for (Map.Entry<View, String> sharedElement : extras.getSharedElements().entrySet()) {
ft.addSharedElement(sharedElement.getKey(), sharedElement.getValue());
}
}
ft.setReorderingAllowed(true);
ft.commit();
// The commit succeeded, update our view of the world
if (isAdded) {
mBackStack.add(destId);
return destination;
} else {
return null;
}
}

@hele-jeremy
Copy link
Author

原生的navigation跳转页面时replace替换Fragment的因此launchSingleTop只能工作在自己跳转自己页面的情况,因此在原生的情况下,机制是launchSingleTop每次都会新建一个新的页面fragment实例,并将上一个自己页面的fragment实例给popupbackstatck 出栈并且将新创建的fragment页面实例给入栈,而改为了hide的机制后, launchSingleTop不应该将老的上一个页面给出栈,而是应该 继续保持老的fragment页面实例在栈中

@KunMinX
Copy link
Owner

KunMinX commented Sep 24, 2021

@hele-jeremy
感谢你的分享,经测试,上述代码可实现预期效果,且在目前已知场景下皆未产生副作用,
为此可以邀请你 pull request 上述设计吗?这可以让你的这次分享出现在贡献名单中。开源不是一个人的战斗,我们希望每位贡献者都能出现在贡献者名单。

@hele-jeremy
Copy link
Author

已提交pr

@KunMinX KunMinX added the 精华 label Sep 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants