说到Jetpack路由组件熟悉的只有ARouter框架?今天带你深入理解功能强大的Navigation架构

public void onAttach(@NonNull Context context) {

super.onAttach(context);

// TODO This feature should probably be a first-class feature of the Fragment system,

// but it can stay here until we can add the necessary attr resources to

// the fragment lib.

if (mDefaultNavHost) {

getParentFragmentManager().beginTransaction()

.setPrimaryNavigationFragment(this)

.commit();

}

}

}

很简单的几行代码,却藏着不少信息:

  1. NavHostFragment是导航宿主Fragment,要实现路由跳转的Fragment都是它的child Fragment。这里就涉及到childFragmentManager,parentFragmentManager等知识了。
  1. mDefaultNavHost是要设置成true,NavHostFragment才能成为主导航Fragment。
  1. 从注释中,可以看出,setPrimaryNavigationFragment()虽然很不起眼,它即将升级为Fragment的一类公民了(first-class)。

2. FragmentManager 回退栈


栈是一种很简单的数据结构。它的特点是“后进先出”。在FragmentManager中回退栈定义如下:

public abstract class FragmentManager{

ArrayList mBackStack;

}

在FragmentTransaction中有addToBackStack(String name)方法,可以将某个方法加入回退栈中。

class FragmentActvitiy1: AppCompatActivity() {

fun addFragmentNotAddToBackStack() {

supportFragmentManager.commit {

setReorderingAllowed(true)

add(R.id.top_fragment_container_view)

}

supportFragmentManager.commit {

setReorderingAllowed(true)

add(R.id.top_fragment_container_view)

}

}

}

class FragmentActvitiy2: AppCompatActivity() {

fun addFragmentNotAddToBackStack() {

supportFragmentManager.commit {

setReorderingAllowed(true)

add(R.id.top_fragment_container_view)

addToBackStack(null)

}

supportFragmentManager.commit {

setReorderingAllowed(true)

add(R.id.top_fragment_container_view)

addToBackStack(null)

}

}

}

上述两段代码,唯一的区别就是FragmentActivity1没有调用addToBackStack()方法,而FragmentActivity2调用了。

FragmentActivity1 按返回键效果如下:

FragmentActivity2 按返回键效果如下:

3. FragmentManager处理返回原理


「handleOnBackPressed()」 处理逻辑如下:

当回退栈中有记录时,调用popBackStackImmediate(),该方法调用popBackStackImmediate(String name, int id, int flags)

**「代码1处」**就是处理当前FragmentManager有主导航Fragment时的返回场景。如果主导航Fragment不为空时,交由childManager处理返回。如果childMananger拦截了返回键处理则返回,否则继续让当前FragmentManager处理。具体场景,后文详解。

「代码2处」 popBackStackState(ArrayListrecords, ArrayListisRecordPop, String name, int id, int flags)的作用是将回退栈中的FragmentTransaction(BackStackRecord)放到records集合中,以备后用。

出栈分为4种情况(简单起见,id不考虑了,否则根据排列组合有8中情况)

| case | name | POP_BACK_STACK_INCLUSIVE |

| — | — | — |

| case1 | null | 0 |

| case2 | not null | 0 |

| case3 | not null | 1 |

| case4 | null | 1 |

POP_BACK_STACK_INCLUSIVE = 1时表示,根据name找到返回栈里面的BackStackRecord,一起出栈。

假设有回退栈如下。我们来走下四种case。

「case->popBackStack(null,0)」

「case2->popBackStack(“s2”,0)」

「case3->popBackStack(“s2”,1)」

「case4->popBackStack(null,1)」

「代码3处」 removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop)真正执行出栈操作。最终执行到executeOpsTogether方法。

4. setPrimaryNavigationFragment


经过前面那么多的铺垫,终于来到讲解本文主角setPrimaryNavigationFragment了(下文简称:“主导航Fragment”)。前文例子,我们都是基于FragmentActivity平铺Fragment场景讲解的。如果Fragment嵌套Fragment,该如何处理返回栈呢。“主导航Fragment”就是为了解决嵌套Fragment而设计的。前文讲到“Fragment必须依附在NavHostFragment上”,其实就是嵌套Fragment了。

从上图我们看到有三种角色。HostActivity,HostFragment,Child Fragment(s)。

HostFragment就是通过成为“主导航Fragment”,接管Activity的处理返回操作,并且将返回操作交由ChildFragment(s)去处理。作用可谓“承上启下”。

文字描述始终有点晦涩难懂。上场景图解。

分两种场景。

| Case | HostFragment |

| — | — |

| Case1 | 不成为主导航Fragment |

| Case2 | 成为主导航Fragment |

「Case1 伪代码如下」

「Case2 伪代码如下」

「返回场景如下」

「Case1」

最后

针对于上面的问题,我总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。
Android进阶视频+面试资料部分截图

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

最后

针对于上面的问题,我总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。
[外链图片转存中…(img-usIUNd48-1715395564465)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值