美文网首页
Android Navigation 避免重建的尝试

Android Navigation 避免重建的尝试

作者: 小强开学前 | 来源:发表于2022-05-03 00:05 被阅读0次

    页面3个Tab,分别为A,B,C
    A页面�内有 ViewPager2,内部有多个子页面D,其余无子 Fragment

    依赖项

    implementation("androidx.navigation:navigation-fragment:2.4.2")
    implementation("androidx.appcompat:appcompat:1.4.1")
    implementation("com.google.android.material:material:1.5.0")
    

    页面布局

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/main_nav"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            app:defaultNavHost="true"
            app:navGraph="@navigation/main_nav_graph" />
    
        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottom_nav_fg_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:menu="@menu/main_nav_menu" />
    </LinearLayout>
    

    1. 使用默认设置,不做任何处理

    mBinding.bottomNavFgMain.setOnItemSelectedListener(item -> {
        // 这里我将 menu 的 id 与 NavDestination 的 id 一致对应
        findNavController().navigate(item.getItemId());
        return true;
    });
    
    测试过程 结果
    APP 启动 A,D初始化 state == null; state == null
    切到B B初始化 state == null; A,D到 onDestroyView
    切到C C初始化 state == null; B 到 onDestroyView
    切到B B1初始化 state == null; C 到 onDestroyView
    切到A A1,D1 初始化 state == null; B1 到 onDestroyView
    多次按返回键 A1->B1->C->B->A->桌面

    其中A1,B1表示每次跳转到的新页面 hashCode 打印出来都是不同的,意味着其实每次都是新建页面,栈内的对象实例一直在增加。返回键只是将这些栈内的实例重新显示。

    state 表示 saveInstanceState

    使用 NavigationUI

    添加依赖

    implementation("androidx.navigation:navigation-ui:2.4.2")
    

    删除之前的跳转逻辑,使用

    NavigationUI.setupWithNavController(mBinding.bottomNavFgMain, findNavController());
    
    测试过程 结果
    APP 启动 A,D初始化 state == null
    切到B B初始化 state == null; A,D到 onDestroyView
    切到C C初始化 state == null; B 到 onDestroy
    切到B B1初始化 state != null; C 到 onDestroy
    切到A A,D 初始化 state == null; B1 到 onDestroy
    切到B B2初始化 state != null; A,D到 onDestroyView
    切到C C1初始化 state == null; B2 到 onDestroy
    多次按返回键 C1->A->桌面

    其中B1、C1表示每次跳转到的新页面 hashCode 打印出来都是不同的。

    总结

    • 不做任何操作的话,Navigation 是单任务栈管理模式,只能往里填充和显示最近实例;
    • NavigationUI#setupWithNavController则是通过配合popUpTosaveState等API,保证只缓存默认导航页面A,其余同级界面离开前会保存状态,不会保留实例。
    • 两者都会重建 UI,无法保存滚动位置等等...至于新版本多任务栈的特性,与避免 UI 创建完全不相干,如果欣赏 YouTube 那种风格的话,可以尝试。

    总之,我个人认为 Navigation 不适合用作传统 APP 多 Tab 切换的主页,用作二级菜单确实不错。

    相关文章

      网友评论

          本文标题:Android Navigation 避免重建的尝试

          本文链接:https://www.haomeiwen.com/subject/yjtbyrtx.html