JackPack原理篇(一):Navigation

JetPack框架出来的时间也比较久了,我记得我是在19年开始接触相关的框架,当时觉得ViewModel、LiveData、Paging2、协程之类的很厉害,很牛逼,很好用。可惜,学是学了,只是当时的环境用不上。不过有意思的是我也学了一下Navigation,当时给的评价是“鸡肋”,学之无用,弃之可惜,而且当时的Navigation总是有这样那样的问题,所以后面就放弃使用了。不过最近在管理Fragment的时候总是听别人说Navigation有多厉害多厉害的,而且正好项目也要对部分代码进行重构,所以重新再学了一下Navigation。不动笔墨不读书,因此在这里记录一下我对Navigation的理解。
Navigation的使用就没必要放上来了,这种烂大街的东西,随手可以搜得到,下面直接讲讲原理吧。

Navigation中值得关注的有两个问题,第一个是:Navigation是如何进行初始化的,即在配置好相关的nav_graph、FragmentContainerView等等之后,它是怎么工作的;第二个是:我们调用的navigate()方法,它是如何实现它的功能的。

先分析第一个问题,以下面的代码为例:

<androidx.fragment.app.FragmentContainerView
            android:id="@+id/main_fragment_container"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintTop_toTopOf="parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph" />

这段代码在FragmentContainerView放置了一个NavHostFragment,NavHostFragment的创建方式有两种,第一种是通过代码方式:NavHostFragment.create() ,第二种方法是通过xml的方式,就比如上面的代码。先分析第一种方式:

    public static NavHostFragment create(@NavigationRes int graphResId,
            @Nullable Bundle startDestinationArgs) {
        Bundle b = null;
        if (graphResId != 0) {
            b = new Bundle();
            b.putInt(KEY_GRAPH_ID, graphResId);
        }
        if (startDestinationArgs != null) {
            if (b == null) {
                b = new Bundle();
            }
            b.putBundle(KEY_START_DESTINATION_ARGS, startDestinationArgs);
        }

        final NavHostFragment result = new NavHostFragment();
        if (b != null) {
            result.setArguments(b);
        }
        return result;
    }

代码很简单,可以看到该方法只做了一件事,就是把导航图的id以及默认导航目的地的参数储存到一个Bundle中,并且放置到一个新创建的NavHostFragment里面。

再看看第二种方式,熟悉Fragment生命周期的都清楚,通过xml里面创建的Fragment,必然会走到onInflate方法中,其代码如下:

public void onInflate(@NonNull Context context, @NonNull AttributeSet attrs,
            @Nullable Bundle savedInstanceState) {
        super.onInflate(context, attrs, savedInstanceState);

        final TypedArray navHost = context.obtainStyledAttributes(attrs,
                androidx.navigation.R.styleable.NavHost);
        final int graphId = navHost.getResourceId(
                androidx.navigation.R.styleable.NavHost_navGraph, 0);
        if (graphId != 0) {
            mGraphId = graphId;
        }
        navHost.recycle();

        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NavHostFragment);
        final boolean defaultHost = a.getBoolean(R.styleable.NavHostFragment_defaultNavHost, false);
        if (defaultHost) {
            mDefaultNavHost = true;
        }
        a.recycle();
    }

这里的代码也很简单,可以看到该方法主要做的也只有一件事:解析出xml里面的defaultNavHost属性和navGraph属性,并且将其记录起来。
根据Fragment的生命周期,其下一步会调到onCreate()方法中,其代码如下:

 public void onCreate(@Nullable Bundle savedInstanceState) {
         ......
        //①创建NavHostController对象
       
        mNavController = new NavHostController(context);
         ......
        //②创建对应的Navigator并储存到NavigatorProvider中
        onCreateNavController(mNavController);
        //③恢复数据
        Bundle navState = null;
        if (savedInstanceState != null) {
            navState = savedInstanceState.getBundle(KEY_NAV_CONTROLLER_STATE);
            if (savedInstanceState.getBoolean(KEY_DEFAULT_NAV_HOST, false)) {
                mDefaultNavHost = true;
                getParentFragmentManager().beginTransaction()
                        .setPrimaryNavigationFragment(this)
                        .commit();
            }
            mGraphId = savedInstanceState.getInt(KEY_GRAPH_ID);
        }

        if (navState != null) {
            // Navigation controller state overrides arguments
            mNavController.restoreState(navState);
        }

      //④将导航图id设置到NavController中
        if (mGraphId != 0) {
            // Set from onInflate()
            mNavController.setGraph(mGraphId);
        } else {
            // See
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值