Git Product home page Git Product logo

smooth-navigation's Issues

连续快速点击item跳转闪退

java.lang.IllegalArgumentException: Navigation action/destination com.kunminx.smoothnavigation:id/action_listFragment_to_detailFragment cannot be found from the current destination Destination(com.kunminx.smoothnavigation:id/detailFragment) label=DetailFragment class=com.kunminx.puremusic.ui.DetailFragment

action跳转,双击崩溃

我的解决方案.. 抛砖引玉

fun NavController.safeNavigate(action: NavDirections) {
    try {
        this.navigate(action)
    } catch (e:Exception){
    }
}

生命周期问题

由FragmentA跳转到FragmentB,FragmentA生命周期为何没有任何变化?

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.e("生命周期","onAttach")
    }

    override fun onStart() {
        super.onStart()
        Log.e("生命周期","onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.e("生命周期","onResume")
    }


    override fun onPause() {
        super.onPause()
        Log.e("生命周期","onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.e("生命周期","onStop")
    }

    override fun onDetach() {
        super.onDetach()
        Log.e("生命周期","onDetach")
    }

java.lang.IllegalArgumentException: Navigation action

2021-04-25 22:42:14.737 19593-19593/com.kunminx.smoothnavigation E/AndroidRuntime: FATAL EXCEPTION: main Process: com.kunminx.smoothnavigation, PID: 19593 java.lang.IllegalArgumentException: Navigation action/destination com.kunminx.smoothnavigation:id/action_listFragment_to_detailFragment cannot be found from the current destination Destination(com.kunminx.smoothnavigation:id/detailFragment) label=DetailFragment class=com.kunminx.puremusic.ui.DetailFragment at androidx.navigation.NavController.navigate(NavController.java:938) at androidx.navigation.NavController.navigate(NavController.java:875) at androidx.navigation.NavController.navigate(NavController.java:861) at androidx.navigation.NavController.navigate(NavController.java:849) at com.kunminx.puremusic.ui.ListFragment.lambda$onCreateView$0$ListFragment(ListFragment.java:60) at com.kunminx.puremusic.ui.-$$Lambda$ListFragment$4BN03aTrC9t10SJQdwnHqZnZ3TQ.onItemClick(Unknown Source:4) at com.kunminx.puremusic.ui.base.adapter.BaseBindingAdapter.lambda$onCreateViewHolder$1$BaseBindingAdapter(BaseBindingAdapter.java:75) at com.kunminx.puremusic.ui.base.adapter.-$$Lambda$BaseBindingAdapter$8LeqcfLWURSbEo3pVSDDYsfV3jg.onClick(Unknown Source:4) at android.view.View.performClick(View.java:7184) at android.view.View.performClickInternal(View.java:7161) at android.view.View.access$3500(View.java:818) at android.view.View$PerformClick.run(View.java:27677) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7562) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

在体验demo的时候点击列表,触发了这个异常。
红米8a,Android10.
没有修改过demo的任何代码。
我点击+添加动态,然后来回添加返回滑动。点击到某一条的时候就遇到这样情况了。

Hi there so i have this issue, and i cant resolve it, please help :)

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.appqueen.quizzmaster, PID: 19760
java.lang.IllegalArgumentException: Navigation action/destination com.appqueen.quizzmaster:id/action_mainFragment_to_quizzListFragment cannot be found from the current destination Destination(com.appqueen.quizzmaster:id/quizzListFragment) label=fragment_quizz_list class=com.appqueen.quizzmaster.view.poslogin.quizzlist.QuizzListFragment
at androidx.navigation.NavController.navigate(NavController.kt:1540)
at androidx.navigation.NavController.navigate(NavController.kt:1472)
at androidx.navigation.NavController.navigate(NavController.kt:1454)
at androidx.navigation.NavController.navigate(NavController.kt:1437)
at com.appqueen.quizzmaster.view.shared.main.MainFragment.onClick(MainFragment.java:257)
at android.view.View.performClick(View.java:7357)
at android.widget.TextView.performClick(TextView.java:14263)
at android.view.View.performClickInternal(View.java:7323)
at android.view.View.access$3200(View.java:849)
at android.view.View$PerformClick.run(View.java:27895)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7266)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)

navArgs()方法不能用

删掉官方的androidx.navigation:navigation-fragment后,获取参数的扩展不能用了,请问咋整
Dingtalk_20201015173626

Duplicate class androidx.navigation.fragment.DialogFragmentNavigator found in modules

    api 'com.kunminx.arch:smooth-navigation:3.9.0-beta1'
    api("androidx.navigation:navigation-fragment-ktx:$nav_version") {
        exclude group: 'androidx.navigation', module: "navigation-fragment"
   }

Duplicate class androidx.navigation.fragment.DialogFragmentNavigator found in modules jetified-smooth-navigation-3.9.0-beta1-runtime (com.kunminx.arch:smooth-navigation:3.9.0-beta1) and navigation-fragment-2.3.5-runtime (androidx.navigation:navigation-fragment:2.3.5)

Navigation 2.4+ Kotlin 重写版本

最新是 Navigation 2.4.2,由于使用 kotlin 重写,并且改动不少,不好把 2.3.x 的改动方式平移到 2.4.x 上。
另外现在 navigation-fragment 中包含 navigation-fragment-ktx,所以不能通过 exclude 解决依赖重复问题,只能拷贝代码到项目上。
2.4.x和2.3.x 版本混用不知道会不会有坑?

launchSingleTop模式跳转页面时,若启动页面时附带了新的arguments,如何处理arguments变更逻辑?

launchSingleTop模式跳转页面时,若启动页面时附带了新的arguments,有什么好的方案来处理因arguments变更而需执行的逻辑么?例如页面为文章详情页,启动页面时需附带文章id参数。【一般我会在onCreate时处理数据初始化的逻辑。对文章详情页的case来说就是接收argument中的文章id参数,交给VM来发起文章数据加载。】

测试场景如下:
当前栈顶:AFragment
NavAction: 由AFragment启动AFragment,附带新的arguments,launchSingleTop = true
此时满足栈顶复用条件,"复用"当前栈顶的AFragment示例(这里复用打个引号,原版Navigation实际上未复用实例)

---------方案对比 start------------
-----原版Navigation 行为-------

  1. 弹出栈顶AFragment实例
  2. 添加新的AFragment实例,arguments赋值为新的arguments

因创建了新实例,因此会执行Fragment onCreate -> onResume一系列生命周期方法,因此可随onCreate使用新的argument完成初始化逻辑。
-----SmoothNavigation行为-------

  1. 保持栈顶AFragment实例不变
  2. 对该实例调用setArguments方法

因生命周期未变更,除setArguments方法外的任何一个回调方法均不会被执行。
---------方案对比 end------------

在使用SmoothNavigation的情况下,除复写setArguments并处理argument变更逻辑外,有无其他的解决方案?

launchSingleTop属性跳转页面问题



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;
}
}

清空back stack后跳转

在看了这篇文章之后,里面有一个写法,目标是和标题一样,行为应该是切换了navigationstartDestination

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_navigation"
    app:startDestination="@id/home_fragment">
    <action
        android:id="@+id/action_login"
        app:destination="@+id/login_navigation"
        app:popUpTo="@id/main_navigation"
        app:popUpToInclusive="true"
        app:launchSingleTop="true"/>
    <fragment
        android:id="@+id/home_fragment"
        android:name="com.example.HomeFragment" />
    <navigation
        android:id="@+id/login_navigation"
        app:startDestination="@id/login_fragment">
        <fragment
            android:id="@+id/login_fragment"
            android:name="com.example.LoginFragment" />
    </navigation>
</navigation>

结果发生了问题,对大佬的严格深有感悟,受制于自身水平,实在没办法探索。

2022-01-18 12:22:03.157 E/AndroidRuntime: FATAL EXCEPTION: main
Process: , PID: 16247
java.lang.RuntimeException: Unable to start activity ComponentInfo{
/
*******.module.main.mine.bankcard.BankCardManagerActivity}: java.lang.UnsupportedOperationException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2877)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2938)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1652)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6441)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:939)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:829)
Caused by: java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at androidx.navigation.fragment.FragmentNavigator.popBackStack(FragmentNavigator.java:109)
at androidx.navigation.NavController.popBackStackInternal(NavController.java:323)
at androidx.navigation.NavController.navigate(NavController.java:1059)
at androidx.navigation.NavController.navigate(NavController.java:944)
at androidx.navigation.NavController.navigate(NavController.java:877)
at androidx.navigation.NavController.navigate(NavController.java:863)
at androidx.navigation.NavController.navigate(NavController.java:851)
at **************.module.main.mine.bankcard.BankCardManagerActivity.initView(BankCardManagerActivity.kt:30)
at com.wsdydeni.baselib.base.BaseActivity.onCreate(BaseActivity.kt:46)
at android.app.Activity.performCreate(Activity.java:6782)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2825)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2938) 
at android.app.ActivityThread.-wrap12(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1652) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6441) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:939) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:829) 

具体是 FragmentNavigator.java:109

boolean isSingleTopReplacement = navOptions != null && !initialNavigation && navOptions.shouldLaunchSingleTop() && (Integer)this.mBackStack.peekLast() == destId;

代码设置NavGraph,二级页面返回后白屏

我在代码里面初始化navGraph

        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.nav_host_fragment_identity) as NavHostFragment
        val navController = NavHostFragment.findNavController(navHostFragment)
        navController.setGraph(
            if(authStatus == "1") R.navigation.nav_identity
            else R.navigation.nav_identity_verify
        )

设置了之后,在某个二级页面返回,白屏了

 Navigation.findNavController(requireActivity(),R.id.nav_host_fragment_identity).navigateUp()

第一次设置navGrpah的日志

2022-01-21 16:12:17.797 D/Nav: --isSingleTopReplacement --- false
2022-01-21 16:12:17.797 D/Nav: --mBackStack.size:0 getFragments().size():0
2022-01-21 16:12:17.797 D/Nav: --Replace --- InitiateVerifyFragment{6b983ed} (35176420-6950-4140-97fe-c1951b65d7a9)

跳转二级页面的日志

2022-01-21 16:12:21.625 D/Nav: --isSingleTopReplacement --- false
2022-01-21 16:12:21.625 D/Nav: --mBackStack.size:1 getFragments().size():1
2022-01-21 16:12:21.625 D/Nav: --Add --- UploadVerifyFragment{9c80c27} (b504e152-121d-4bc7-84cf-efa6358bf1ca)
2022-01-21 16:12:21.626 D/Nav: --Hide --- InitiateVerifyFragment{ddb6b77} (55ca39c0-09e1-4355-b0dc-c311cb6af423 id=0

返回的时候没有日志,只隐藏了二级页面,一级页面也没显示,导致白屏了。

【 提问须知 】

如有 bug,请另外 new 一个 issue ⚠️⚠️⚠️

本项目开 issue 规范:

  1. 有任何 bug 都欢迎及时开 issue,我看到后予以处理。
  2. 如有使用上的疑问,请先认真阅读 Readme 和源码 sample,在没有找到答案后,另外开 issue。
  3. 如开 issue 是为了发表个人见解,请务必 客观、具体、严谨;严禁草率、乱入、带节奏:

务必注明观点所对应的场景,并附上完整可复现的代码,

不然缺乏一致的前提依据来有效交流!

任何缺乏实证依据和因果逻辑的泛泛而谈,都可能对其他使用者造成困扰。

在发表个人见解前,请先确保自己认真阅读过源码。这是对自己、对作者、对其他读者最起码的尊重。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.