IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> ??即学即用Android Jetpack - Navigation??(从构建到源码,十分详细) -> 正文阅读

[移动开发]??即学即用Android Jetpack - Navigation??(从构建到源码,十分详细)

前言

在移动开发中,对开发者来说不同的人具有不同的能力。就像读一本书一样,一千个读者,有一千个哈姆雷特。但不管怎样,只要你是个软件开发者你就必须学习windows或Linux等操作系统的运行原理。就不扯这么多了直接上干货。
【由于文中篇幅较长,提前预告:文末有大量手写框架源码及架构思维资料,需要的可直接跳越至文末领取】

实战

在实战之前,我们先来了解一下 Navigation 中最关键的三要素,他们是:

  • Navigation Graph (New XML resource)
    如我们的第一张图所示,这是一个新的资源文件,用户在可视化界面可以看出
    他能够到达的 Destination (用户能够到达的屏幕界面),以及流程关系。
  • NavHostFragment (Layou XML view)
    当前 Fragment 的容器
  • NavController (Kotlin/Javaobject)
    导航的控制者

可能我这么解释还是有点抽象,做一个不是那么恰当的比喻,我们可以将 Navigation Graph 看作一个地图,
NavHostFragment 看作一个车,以及把 NavController 看作车中的方向盘, Navigation Graph 中可以看出各个地点(Destination)和通往各个地点的路径, NavHostFragment 可以到达地图中的各个目的地,但是决定到什么目的地还是方向盘 NavController ,虽然它取决于开车人(用户)。

第一步 添加依赖

模块层的 build.gradle 文件需要添加:

ext.navigationVersion = "2.0.0" 
dependencies { 
                //...
               implementation "androidx.navigation:navigation-fragment- ktx:$rootProject.navigationVersion" 
               implementation "androidx.navigation:navigation-ui-ktx:$rootProject.navigationVersion"
 }

如果你要使用 SafeArgs 插件,还要在项目目录下的 build.gradle 文件添加:

buildscript { 
      ext.navigationVersion = "2.0.0" 
      dependencies { 
            classpath "androidx.navigation:navigation-safe-args-gradle- plugin:$navigationVersion" 
      } 
}

以及模块下面的 build.gradle 文件添加:

apply plugin: 'kotlin-android-extensions' 
apply plugin: 'androidx.navigation.safeargs'

第二步 创建navigation导航

  1. 创建基础目录:资源文件 res 目录下创建 navigation 目录 -> 右击 navigation 目录New一个 Navigation resource file
  2. 创建一个
Destination

,如果说

navigation

是我们的导航工具,

Destination

是我们的目的地,在此之前,我已经写好了一个

WelcomeFragment

LoginFragment

RegisterFragment

,添加

Destination

的操作完成后如下所示:

添加Destination

除了可视化界面之外,我们仍然有必要看一下里面的内容组成, login_navigation.xml :

<navigation
      ...
      android:id="@+id/login_navigation"
      app:startDestination="@id/welcome">

      <fragment
          android:id="@+id/login"
          android:name="com.joe.jetpackdemo.ui.fragment.login.LoginFragment"
          android:label="LoginFragment"
          tools:layout="@layout/fragment_login"
          />

       <fragment
          android:id="@+id/welcome"
          android:name="com.joe.jetpackdemo.ui.fragment.login.WelcomeFragment"
          android:label="LoginFragment"
          tools:layout="@layout/fragment_welcome">
          <action
                .../>
          <action
                .../>
          </fragment>

      <fragment
          android:id="@+id/register"
          android:name="com.joe.jetpackdemo.ui.fragment.login.RegisterFragment"    
          android:label="LoginFragment"
          tools:layout="@layout/fragment_register"
          >
          <argument
                .../>
      </fragment>
</navigation>

我在这里省略了一些不必要的代码。让我们看一下 navigation标签 的属性:

app:startDestination 默认的起始位置

第三步 建立 NavHostFragment

我们创建一个新的 LoginActivity ,在 activity_login.xml 文件中:

<androidx.constraintlayout.widget.ConstraintLayout
      ...>

      <fragment
          android:id="@+id/my_nav_host_fragment"
          android:name="androidx.navigation.fragment.NavHostFragment"
          app:navGraph="@navigation/login_navigation"
          app:defaultNavHost="true"
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

有几个属性需要解释一下:

  • android:name
    值必须是androidx.navigation.fragment.NavHostFragment,声明这是一个 NavHostFragment
  • app:navGraph
    存放的是第二步建好导航的资源文件,也就是确定了Navigation Graph
  • app:defaultNavHost="true"
    与系统的返回按钮相关联

第四步 界面跳转、参数传递和动画

在 WelcomeFragment 中,点击登录和注册按钮可以分别跳转到 LoginFragment 和 RegisterFragment 中。

WelcomeFragment.
这里我使用了两种方式实现:

方式一 利用ID导航

目标: WelcomeFragment 携带 key 为 name 的数据跳转到 LoginFragment , LoginFragment 接收后显示。
Have a account ? Login 按钮的点击事件如下:

btnLogin.setOnClickListener {
          // 设置动画参数
          val navOption = navOptions {
                  anim {
                        enter = R.anim.slide_in_right
                        exit = R.anim.slide_out_left
                        popEnter = R.anim.slide_in_left
                        popExit = R.anim.slide_out_right
                  }
          }
          // 参数设置
          val bundle = Bundle()
          bundle.putString("name","TeaOf")
          findNavController().navigate(R.id.login, bundle,navOption)
}

后续 LoginFragment 的接收代码比较简单,直接获取Fragment中的 Bundle 即可,这里不再出示代码。最后的效
果:

LoginFragment

方式二 利用 Safe Args **

目标: WelcomeFragment 通过 Safe Args 将数据传到 RegisterFragment , RegisterFragment 接收后显示。
再看一下已经展示过的 login_navigation.xml :

<navigation
      ...>
      <fragment
          ...
          />

      <fragment
          android:id="@+id/welcome"
          >
          <action
              android:id="@+id/action_welcome_to_login"
              app:destination="@id/login"/>
          <action
              android:id="@+id/action_welcome_to_register"
              app:enterAnim="@anim/slide_in_right"
              app:exitAnim="@anim/slide_out_left"
              app:popEnterAnim="@anim/slide_in_left"
              app:popExitAnim="@anim/slide_out_right"
              app:destination="@id/register"/>
      </fragment>
      <fragment
          android:id="@+id/register"
          ...
          >
          <argument
              android:name="EMAIL"
              android:defaultValue="2005@qq.com"
              app:argType="string"/>
      </fragment>
</navigation>

细心的可能已经观察到 navigation 目录下的 login_navigation.xml 资源文件中的 action 标签和 argument
标签,这里需要解释一下:

  • app:destination
    跳转完成到达的 fragment 的Id
  • app:popUpTo
    将 fragment 从 栈 中弹出,直到某个Id的 fragment

argument标签

  • android:name
    标签名字
  • app:argType
    标签的类型
  • android:defaultValue
    默认值

点击Android studio中的Make Project按钮,可以发现系统为我们生成了两个类:

系统生成的类

WelcomeFragment

中的

JOIN US

按钮点击事件:

btnRegister.setOnClickListener {
        val action = WelcomeFragmentDirections
              .actionWelcomeToRegister()
              .setEMAIL("TeaOf1995@Gamil.com")
        findNavController().navigate(action)
}

RegisterFragment 中的接收:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // ...
        val safeArgs:RegisterFragmentArgs by navArgs()
        val email = safeArgs.email
        mEmailEt.setText(email)
}

以及效果:


RegisterFragment
需要提及的是,如果不用

Safe Args

,

action

可以由

Navigation.createNavigateOnClickListener(R.id.next_action, null)

方式生成,感兴趣的可以自行编写。

更多

Navigation 可以绑定 menus 、 drawers 和 bottom navigation ,这里我们以 bottom navigation 为例,我先在
navigation 目录下新创建了 main_navigation.xml ,接着新建了 MainActivity ,下面则是
activity_main.xml :

<LinearLayout
      ...>
      <fragment
          android:id="@+id/my_nav_host_fragment"
          android:name="androidx.navigation.fragment.NavHostFragment"
          android:layout_width="match_parent"
          app:navGraph="@navigation/main_navigation"
          app:defaultNavHost="true"
          android:layout_height="0dp"
          android:layout_weight="1"/>
      <com.google.android.material.bottomnavigation.BottomNavigationView
          android:id="@+id/navigation_view"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:background="@android:color/white"
          app:itemIconTint="@color/colorAccent"
          app:itemTextColor="@color/colorPrimary"
          app:menu="@menu/menu_main"/>
  </LinearLayout>

MainActivity 中的处理也十分简单:

class MainActivity : AppCompatActivity() {
          
          lateinit var bottomNavigationView: BottomNavigationView
          
          override fun onCreate(savedInstanceState: Bundle?) {
              //...
              val host: NavHostFragment =
          supportFragmentManager.findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment
              val navController = host.navController
              initWidget()
              initBottomNavigationView(bottomNavigationView,navController)
          }

          private fun initBottomNavigationView(bottomNavigationView: BottomNavigationView, navController: NavController) {
              bottomNavigationView.setupWithNavController(navController)
          }
          private fun initWidget() {
              bottomNavigationView = findViewById(R.id.navigation_view)
          }
}

效果:

结束

更多手写项目源码请往下看(文末可直接领取)

  • Data Binding
  • ViewModel & LiveData
  • Room
  • Paging
  • WorkManger
  • Paging 3

MVC/MVP/MVVM

  • MVC框架-ASP.NET窗体
  • MVC框架-第一应用程序
  • MVC框架-文件夹
  • MVC框架-模型
  • MVC框架-控制器
  • MVC框架-视图
  • MVC框架-布局
  • MVP架构设计:Google官方MVP思想解读
  • 开源MVP框架
  • MVC、MVP、MVVM,到底该怎么选?

大厂架构演进之路

  • 抖音 iOS 工程架构演进
  • 美团外卖 Android 平台化架构演进实践
  • 安居客 Android 项目架构演进
  • 携程 Android App 插件化和动态加载实践
  • 微信Android客户端架构演进之路
  • 千万级用户的 Android 客户端是如何养成的 | 架构师实践日
  • 手机淘宝构架演化实践
  • 英语流利说 Android 架构演进

我建立了一个编程资料共享学习Q裙:裙号是793544421,也可直接添加我的唯心:【Keaiduoooo_】。我整理了一系列编程学习视频、Android技术原理、手写源码、架构思维、书籍、笔记等等,需要文中资料的同学,进群即可获得。【技术学习交流,广告勿入】,技术是有边界的,但是学习是无界的,群里会有一些大神帮忙解答,有时你闷头想一天,不如别人的三言两语就醍醐灌顶。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:45:30  更:2021-07-31 16:46:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/7 9:56:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码