日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Navigation源碼解析

電子工程師 ? 來源:Android開發(fā)之旅 ? 作者:四爺 ? 2021-06-15 16:38 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

Navigation源碼解析

谷歌推出Navigation主要是為了統(tǒng)一應(yīng)用內(nèi)頁(yè)面跳轉(zhuǎn)行為。本文主要是根據(jù)Navigation版本為2.1.0 的源碼進(jìn)行講解。

androidx.navigation2.1.0’ ‘a(chǎn)ndroidx.navigation2.1.0’ ‘a(chǎn)ndroidx.navigation2.1.0’ ‘a(chǎn)ndroidx.navigation2.1.0’

Navigation的使用很簡(jiǎn)單,在創(chuàng)建新項(xiàng)目的時(shí)候可以直接選擇 Bottom Navigation Activity 項(xiàng)目,這樣默認(rèn)就已經(jīng)幫我們實(shí)現(xiàn)了相關(guān)頁(yè)面邏輯。

Navigation的源碼也很簡(jiǎn)單,但是卻涉及到很多的類,主要有以下幾個(gè):

Navigation提供查找NavController方法

NavHostFragment用于承載導(dǎo)航的內(nèi)容的容器

NavController通過navigate實(shí)現(xiàn)頁(yè)面的跳轉(zhuǎn)

Navigator是一個(gè)abstract,有四個(gè)主要實(shí)現(xiàn)類

NavDestination導(dǎo)航節(jié)點(diǎn)

NavGraph導(dǎo)航節(jié)點(diǎn)頁(yè)面集合

我們首先從NavHostFragment入手查看,因?yàn)樗侵苯佣x在我們的XML文件中的,我們直接查看器生命周期方法 onCreate :

@CallSuper @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Context context = requireContext();

mNavController = new NavHostController(context); //1 mNavController.setLifecycleOwner(this);

。。.。

onCreateNavController(mNavController);//2

。。.。 }

注釋1處 直接創(chuàng)建了NavHostController 并通過 findNavController 方法暴露給外部調(diào)用者。NavHostController是繼承自NavController的。注釋2處代碼如下:

@CallSuper protected void onCreateNavController(@NonNull NavController navController) { navController.getNavigatorProvider().addNavigator( new DialogFragmentNavigator(requireContext(), getChildFragmentManager())); navController.getNavigatorProvider().addNavigator(createFragmentNavigator()); }

通過navController獲取NavigatorProvider并向其中添加了兩個(gè)Navigator,分別為DialogFragmentNavigator和FragmentNavigator。另外在NavController的構(gòu)造方法中還添加了另外兩個(gè)Navigator,如下:

public NavController(@NonNull Context context) { 。。.。 mNavigatorProvider.addNavigator(new NavGraphNavigator(mNavigatorProvider)); mNavigatorProvider.addNavigator(new ActivityNavigator(mContext));}

他們都是Navigator的實(shí)現(xiàn)類。分別對(duì)應(yīng)于DialogFragment、Fragment和Activity的頁(yè)面跳轉(zhuǎn)。大家可能對(duì)于NavGraphNavigator一些好奇,它是用在什么地方的呢?其實(shí)我們?cè)赬ML中配置的navGraph對(duì)應(yīng)的navigation跟節(jié)點(diǎn)文件中的 startDestination 就是通過NavGraphNavigator來實(shí)現(xiàn)跳轉(zhuǎn)的。這也是它目前唯一的用途。

各個(gè)Navigator通過復(fù)寫 navigate 方法來實(shí)現(xiàn)各自的跳轉(zhuǎn)邏輯。這里重點(diǎn)強(qiáng)調(diào)下 FragmentNavigator 的實(shí)現(xiàn)邏輯:

public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args, @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {

。。.。

final Fragment frag = instantiateFragment(mContext, mFragmentManager, className, args); frag.setArguments(args); final FragmentTransaction ft = mFragmentManager.beginTransaction();

。。.。

ft.replace(mContainerId, frag); //1

。。.。}

最關(guān)鍵的一行代碼就是注釋1 處。他是通過 replace 來加載 Fragment 的 ,這不符合我們實(shí)際的開發(fā)邏輯。文章后續(xù)會(huì)講解如何自定義 FragmentNavigator 來避免 Fragment 在切換的時(shí)候 生命周期的執(zhí)行。

回到上文中的 navController 獲取的 NavigatorProvider 其內(nèi)部是維護(hù)了一個(gè)HashMap來存儲(chǔ)相關(guān)的Navigator信息。通過獲取到Navigator的注解 Name 為key 和 Navigator 的 getClass為 value 進(jìn)行存儲(chǔ)。

我們?cè)诨氐缴衔闹械?onCreate 方法:

@CallSuper@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Context context = requireContext();

。。.。

if (mGraphId != 0) { mNavController.setGraph(mGraphId); } else {

。。.。

if (graphId != 0) { mNavController.setGraph(graphId, startDestinationArgs); } }}

這里通過 mNavController 調(diào)用了 setGraph 。這里主要是為了解析我們的 XML 中配置的mobile_navigation節(jié)點(diǎn)信息文件。會(huì)根據(jù)不同的節(jié)點(diǎn)來各自解析。

@NonNullprivate NavDestination inflate(@NonNull Resources res, @NonNull XmlResourceParser parser, @NonNull AttributeSet attrs, int graphResId) throws XmlPullParserException, IOException {

Navigator navigator = mNavigatorProvider.getNavigator(parser.getName()); final NavDestination dest = navigator.createDestination();

dest.onInflate(mContext, attrs);

。。.。

final String name = parser.getName(); if (TAG_ARGUMENT.equals(name)) { // argument 節(jié)點(diǎn) inflateArgumentForDestination(res, dest, attrs, graphResId); } else if (TAG_DEEP_LINK.equals(name)) { // deeplink 節(jié)點(diǎn) inflateDeepLink(res, dest, attrs); } else if (TAG_ACTION.equals(name)) { // action 節(jié)點(diǎn) inflateAction(res, dest, attrs, parser, graphResId); } else if (TAG_INCLUDE.equals(name) && dest instanceof NavGraph) { // include 節(jié)點(diǎn) final TypedArray a = res.obtainAttributes(attrs, R.styleable.NavInclude); final int id = a.getResourceId(R.styleable.NavInclude_graph, 0); ((NavGraph) dest).addDestination(inflate(id)); a.recycle(); } else if (dest instanceof NavGraph) { // NavGraph 節(jié)點(diǎn) ((NavGraph) dest).addDestination(inflate(res, parser, attrs, graphResId)); } }

return dest;}

通過獲取 NavInflater 來對(duì)其進(jìn)行解析。解析后返回 NavGraph ,NavGraph是繼承自 NavDestination的。里面主要是保存了所有解析出來的節(jié)點(diǎn)信息。

最后簡(jiǎn)單的總結(jié)下就是通過 NavHostFragment 獲取到NavContorl并存儲(chǔ)了相關(guān)的Navigator信息。通過各自的navigate方法進(jìn)行頁(yè)面的跳轉(zhuǎn)。通過setGraph來解析配置的頁(yè)面節(jié)點(diǎn)信息,并封裝為NavGraph對(duì)象。里面通過SparseArray來存儲(chǔ) Destination 信息。

自定義Navigator上文中我們說了需要自定義自己的 Navigator 用于承載 Fragment 。主要的實(shí)現(xiàn)思路就是繼承現(xiàn)有的 FragmentNavigator 并復(fù)寫其 navigate 方法,將其中的 replace 方法 替換為 show 和 hide 方法 來完成 Fragment 的切換。

那么我們自定義的 Navigator 如何才能讓系統(tǒng)識(shí)別呢?這也簡(jiǎn)單,只要給我們的 類加上注解 @Navigator.Name(value) 那么他就是一個(gè) Navigator 了。最后通過上文中分析的思路 在將其加入到NavigatorProvider 中 即可。

具體的自定義Navigator 已經(jīng)在項(xiàng)目 Android Jetpack架構(gòu)開發(fā)組件化應(yīng)用實(shí)戰(zhàn)(https://github.com/winlee28/Jetpack-WanAndroid) 中了,類名:FixFragmentNavigator。大家可以自行去看下。這里就將核心的代碼貼出來看下:

@Navigator.Name(“fixFragment”) //新的 Navigator 名稱class FixFragmentNavigator(context: Context, manager: FragmentManager, containerId: Int) : FragmentNavigator(context, manager, containerId) {

override fun navigate( destination: Destination, args: Bundle?, navOptions: NavOptions?, navigatorExtras: Navigator.Extras? ): NavDestination? {

。。.。

//ft.replace(mContainerId, frag)

/** * 1、先查詢當(dāng)前顯示的fragment 不為空則將其hide * 2、根據(jù)tag查詢當(dāng)前添加的fragment是否不為null,不為null則將其直接show * 3、為null則通過instantiateFragment方法創(chuàng)建fragment實(shí)例 * 4、將創(chuàng)建的實(shí)例添加在事務(wù)中 */ val fragment = mManager.primaryNavigationFragment //當(dāng)前顯示的fragment if (fragment != null) { ft.hide(fragment) }

var frag: Fragment? val tag = destination.id.toString() frag = mManager.findFragmentByTag(tag) if (frag != null) { ft.show(frag) } else { frag = instantiateFragment(mContext, mManager, className, args) frag.arguments = args ft.add(mContainerId, frag, tag) }

。。.。 }}

自定義完成好,還需要將 mobile_navigation 的節(jié)點(diǎn)中遠(yuǎn) fragment 替換為 fixFragment 節(jié)點(diǎn)。并刪除布局文件中NavHostFragment 節(jié)點(diǎn)的

app:navGraph=“@navigation/mobile_navigation”

信息,因?yàn)槲覀冃枰謩?dòng)將 FixFragmentNavigator 和 NavControl 進(jìn)行關(guān)聯(lián)。

//添加自定義的FixFragmentNavigatornavController = Navigation.findNavController(this, R.id.nav_host_fragment)val fragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragmentval fragmentNavigator = FixFragmentNavigator(this, supportFragmentManager, fragment!!.id)navController.navigatorProvider.addNavigator(fragmentNavigator)

navController.setGraph(R.navigation.mobile_navigation)

這樣就完成了自定義 Navigator 實(shí)現(xiàn)切換 Tab 的時(shí)候 Fragment 生命周期不會(huì)重新執(zhí)行了。

具體代碼邏輯詳見:Android Jetpack架構(gòu)開發(fā)組件化應(yīng)用實(shí)戰(zhàn)(https://github.com/winlee28/Jetpack-WanAndroid)

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Android
    +關(guān)注

    關(guān)注

    12

    文章

    4035

    瀏覽量

    134552
  • XML
    XML
    +關(guān)注

    關(guān)注

    0

    文章

    190

    瀏覽量

    34587
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    689

    瀏覽量

    31524

原文標(biāo)題:Navigation源碼解析及自定義FragmentNavigator詳解

文章出處:【微信號(hào):AndroidPush,微信公眾號(hào):Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    WebRTC源碼級(jí)深度解析(完結(jié)) (讠果xingkeit-top)#WebRTC #源碼

    源碼
    jf_82580774
    發(fā)布于 :2026年03月30日 15:22:21

    Labview 解析dxf文件并顯示

    上一期開了一個(gè)帖子講Labview導(dǎo)入dxf文件,解析和顯示dxf文件,今天繼續(xù)繼續(xù)分享常用圖元的解析與顯示方法。 LINE :用文本方式打開dxf 文件,搜索出直線部分,并摘取,可以得到
    發(fā)表于 12-01 11:28

    Labview 解析dxf文件并顯示<一>

    Labview軟件開發(fā)過程中,大家會(huì)遇到導(dǎo)入dxf文件的需要,今天開個(gè)帖子,聊聊如何解析和顯示dxf文件,同時(shí)用圖表來顯示。 首先來介紹下dxf, 簡(jiǎn)單來說他就是圖形文件的一種文本格式,具有固定
    發(fā)表于 11-14 22:45

    醫(yī)院隨訪管理系統(tǒng)源碼,三級(jí)隨訪系統(tǒng)源碼,Java+Springboot,Vue,Ant-Design+MySQL5

    Java版隨訪系統(tǒng)源碼,醫(yī)院隨訪管理系統(tǒng)源碼,三級(jí)隨訪系統(tǒng)源碼,B/S前后端分離架構(gòu),自主版權(quán),落地案例。 技術(shù)框架:Java+Springboot,Vue,Ant-Design+MySQL5 開發(fā)
    的頭像 發(fā)表于 11-08 14:48 ?755次閱讀
    醫(yī)院隨訪管理系統(tǒng)<b class='flag-5'>源碼</b>,三級(jí)隨訪系統(tǒng)<b class='flag-5'>源碼</b>,Java+Springboot,Vue,Ant-Design+MySQL5

    Swift Navigation與導(dǎo)遠(yuǎn)科技合作打造高精度衛(wèi)星定位解決方案

    2025 年 11 月 4 日,導(dǎo)遠(yuǎn)科技與面向大眾市場(chǎng)的精準(zhǔn)定位技術(shù)全球領(lǐng)導(dǎo)者 Swift Navigation 共同宣布, 導(dǎo)遠(yuǎn) NAV3120 高精度 GNSS 定位模組與 Swift
    的頭像 發(fā)表于 11-06 16:07 ?979次閱讀

    E203工程源碼時(shí)鐘樹解析

    的system.v文件以及引腳約束文件,和rtl文件夾內(nèi)的源碼,我們參考源碼繪制了E203在MCU200T的時(shí)鐘樹,方便我們團(tuán)隊(duì)對(duì)E203源碼的時(shí)鐘進(jìn)行修改,分享如下:
    發(fā)表于 10-29 07:25

    AT組件無法正確解析bin文件怎么解決?

    通過ESP32接受網(wǎng)絡(luò)數(shù)據(jù),然后寫入MCU中,但是發(fā)現(xiàn)在解析bin文件的時(shí)候,會(huì)自動(dòng)添加字符。應(yīng)該是換行符號(hào)的解析出現(xiàn)了問題。有什么好辦法嗎?
    發(fā)表于 09-28 08:36

    mqtt dns解析失敗是為什么?

    解析域名的ip地址就能正常連上,而直接解析域名就不行,為什么呢
    發(fā)表于 09-16 06:38

    智能小車設(shè)計(jì)源碼和圖紙資料

    智能小車設(shè)計(jì)源碼和圖紙
    發(fā)表于 08-25 15:38 ?1次下載

    全新導(dǎo)航庫(kù)Jetpack Navigation 3發(fā)布

    在應(yīng)用中的不同屏幕之間導(dǎo)航理應(yīng)簡(jiǎn)單明了。然而,構(gòu)建穩(wěn)健、可擴(kuò)展且賞心悅目的導(dǎo)航體驗(yàn)卻并非易事。多年來,Jetpack Navigation 庫(kù)一直是開發(fā)者的重要工具,但隨著 Android 界面格局的演變,尤其是 Jetpack Compose 的興起,我們意識(shí)到是時(shí)候探索一種全新的解決方案了。
    的頭像 發(fā)表于 08-06 13:56 ?1563次閱讀

    【匯思博SEEK100開發(fā)板試用體驗(yàn)】06 天氣app--使用組件導(dǎo)航實(shí)現(xiàn)設(shè)置頁(yè)及頁(yè)面跳轉(zhuǎn)

    1 前言 本次要完成組件導(dǎo)航跳轉(zhuǎn)頁(yè)面功能,實(shí)現(xiàn)設(shè)置頁(yè)和主頁(yè)的跳轉(zhuǎn)。 2 組件導(dǎo)航 (Navigation) 2.1 簡(jiǎn)介 組件導(dǎo)航(Navigation)主要用于實(shí)現(xiàn)頁(yè)面間以及組件內(nèi)部的頁(yè)面跳轉(zhuǎn)
    發(fā)表于 07-09 16:57

    從“抓瞎”到“精準(zhǔn)到0.01m”:我們是怎么調(diào)教機(jī)器人不亂動(dòng)的?

    2025ICRASim2Rea獲獎(jiǎng)隊(duì)伍給我們帶來MuJoCo+ROS2閉環(huán)控制與精準(zhǔn)視覺抓取全流程解析項(xiàng)目主要包括Communication、Envs、Navigation
    的頭像 發(fā)表于 07-01 20:30 ?3882次閱讀
    從“抓瞎”到“精準(zhǔn)到0.01m”:我們是怎么調(diào)教機(jī)器人不亂動(dòng)的?

    鴻蒙5開發(fā)寶藏案例分享---PC開發(fā)案例解析

    鴻蒙PC/2in1開發(fā)寶藏指南:官方案例實(shí)戰(zhàn)解析 大家好呀! 最近在折騰鴻蒙的PC/2in1應(yīng)用開發(fā),才發(fā)現(xiàn)官方文檔里藏了一堆超實(shí)用的案例!這些案例就像“隱藏關(guān)卡”,能幫你少踩80%的坑。今天我就把
    發(fā)表于 06-12 16:07

    【經(jīng)驗(yàn)分享】在Omni3576上編譯Redis-8.0.2源碼,并安裝及性能測(cè)試

    本文首先介紹Redis是什么,然后介紹如何在Omni3576上編譯Redis-8.0.2源碼,以及從源碼編譯、安裝Redis,最后介紹如何在Omni3576上運(yùn)行Redis性能測(cè)試,并與樹莓派5上的結(jié)果進(jìn)行對(duì)比。一、Redis是什么維基百科的介紹是:Redi
    的頭像 發(fā)表于 06-05 08:05 ?1114次閱讀
    【經(jīng)驗(yàn)分享】在Omni3576上編譯Redis-8.0.2<b class='flag-5'>源碼</b>,并安裝及性能測(cè)試

    鴻蒙5開發(fā)寶藏案例分享---一多分欄開發(fā)實(shí)踐

    ):清爽單欄 ? 折疊屏(md):優(yōu)雅雙欄 ? 平板(lg):專業(yè)三欄 ? 核心裝備庫(kù) Navigation組件 - 路由容器三合一 // 自適應(yīng)切換單雙欄的魔法 Navigation
    發(fā)表于 06-03 12:03
    青铜峡市| 新龙县| 曲阜市| 任丘市| 仪陇县| 桐柏县| 三门县| 满洲里市| 曲阜市| 遂平县| 资兴市| 北票市| 遂溪县| 故城县| 衡阳县| 湘西| 土默特左旗| 牟定县| 延寿县| 安义县| 乌审旗| 额济纳旗| 上饶市| 洞头县| 武川县| 隆回县| 邯郸县| 新乐市| 马龙县| 军事| 广河县| 中牟县| 阳山县| 资中县| 信丰县| 茌平县| 茶陵县| 靖宇县| 喀喇| 岑溪市| 辛集市|