当前位置: 首页 > news >正文

【Jetpack】Navigation 导航组件 ⑤ ( NavigationUI 类使用 )

文章目录

  • 一、NavigationUI 类简介
  • 二、NavigationUI 类使用流程
    • 1、创建 Fragment
    • 2、创建 NavigationGraph
    • 3、Activity 导入 NavHostFragment
    • 4、创建菜单
    • 5、Activity 界面开发 NavigationUI 的主要逻辑 ( 重点 )
      • a、添加 Fragment 布局
      • b、处理 Navigation 导航逻辑 ( 重点 )
      • c、启用菜单选项
      • d、使用菜单进行 NavigationUI 导航
      • e、支持导航回退功能
  • 三、完整源码示例 - NavigationUI 类使用
    • 1、Fragment 相关源码
      • a、FragmentA 界面的 Kotlin 源码和布局文件
      • b、FragmentB 界面的 Kotlin 源码和布局文件
    • 2、NavigationGraph 相关源码
    • 3、MainActivity 主界面相关源码 ( 重点 )
    • 4、执行结果


代码地址 :

  • CSDN ( 本博客代码快照 | 推荐下载 0 积分 ) : https://download.csdn.net/download/han1202012/88251933
  • GitHub ( 可能已经覆盖 ) : https://github.com/han1202012/Navigation

NavigationUI 类支持一些系统自带的控件 , 配置后 , 自动跳转 Fragment 界面的功能 , 使用起来非常简洁 , 支持的可配置 Navigation 跳转的控件有 :

  • ActionBar
  • ToolBar
  • CollapsingToolbarLayout
  • Menu

在 Android 开发中 , NavigationUI 是 用于构建 和 管理应用程序导航界面 的重要工具 , 可以极大地提高开发效率 ;





一、NavigationUI 类简介



NavigationUI 是 Google 官方提供的 用于管理 Navigation 导航的组件 , 属于 Android 系统的 Jetpack 工具包 ;

借助 NavigationUI 可以很方便的 创建和组织应用程序的导航界面 ;

如 : 构建复杂的导航结构,垂直或水平的主菜单 , 侧边栏 , 抽屉导航栏等 ;


开发者 可以通过 NavigationUI 轻松地管理页面的转换和导航 ;

NavigationUI 提供了一些静态方法来处理 顶部应用栏 / 抽屉式导航栏 / 底部导航栏中 的界面导航 ;


本篇博客中介绍一种使用场景 : 使用 AppBar 中的菜单选项控制 Navigation 界面跳转 ;

在 Activity 中 , 使用 Navigation 组件 切换 Fragment 界面时 , 除了进行界面切换之外 , 不同的界面对应的顶部 标题栏 AppBar 需要进行相应的改变 ;

Navigation 组件中 , 提供了 NavigationUI 类 , 统一管理 Fragment 页面切换相关的 UI 改变 ;





二、NavigationUI 类使用流程



本章节介绍使用 AppBar 中的菜单选项控制 Navigation 界面跳转 的流程 ;


1、创建 Fragment


创建两个 Fragment , 分别作为要 互相跳转 的 两个界面 ;

右键点击包名 , 选择 " New / Fragment / Fragment (Blank) " 选项 ,

在这里插入图片描述

在弹出的界面中 , 输入 Fragment 名称 , 创建新的 Fragment ;

在这里插入图片描述

创建 Fragment 时 , 会自动生成对应的 布局文件 :

在这里插入图片描述


注意 : 该操作比较坑 , 生成 Fragment 时 , 会自动添加 Kotlin 语言插件的 Gradle 依赖 , 必要时可以删除该依赖 ; 自动生成的依赖没有配置 Maven 源 , 会报错 ;

buildscript {dependencies {classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0-RC2'}
}

2、创建 NavigationGraph


创建完 Fragment 之后 , 才能开始创建 NavigationGraph , 否则没有对应的 Fragment 选项 ;

创建 NavigationGraph ,

右键点击 res 目录 , 选择 " New / Android Resource File " 选项 ,

在这里插入图片描述

在弹出的 " New Resource File " 对话框中 , 设置 文件名 , 资源类型 , 目录名称 ;

在这里插入图片描述

下面开始编辑 NavigationGraph , 进入 Design 模式后 , 会提示 Design editor is unavailable until after a successful project sync , 这是因为创建 Fragment 之后 , 还没有进行第一次编译 ,

在这里插入图片描述

选择 " 菜单栏 / Build / Make Project " 选项 , 编译一次应用 ;

在这里插入图片描述

编译成功之后 , 就可以使用 NavigationGraph 的 Design 模式 ;

在这里插入图片描述

点击 " New Destination " 按钮 , 添加两个 Fragment 到 NavigationGraph 中 ;

在这里插入图片描述

将两个 Fragment 添加到 NavigationGraph 中 , 不需要做其它配置 ;

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/my_navigation_graph"app:startDestination="@id/fragmentA"><fragmentandroid:id="@+id/fragmentA"android:name="kim.hsl.app2.FragmentA"android:label="fragment_a"tools:layout="@layout/fragment_a" /><fragmentandroid:id="@+id/fragmentB"android:name="kim.hsl.app2.FragmentB"android:label="fragment_b"tools:layout="@layout/fragment_b" />
</navigation>

在这里插入图片描述

设置默认的 Fragment , 在根标签 navigation 中 ,

app:startDestination="@id/fragmentA"

配置 , 用于配置默认的初始 Fragment 是哪一个 ;


3、Activity 导入 NavHostFragment


进入 Launcher 界面 MainActivity 的布局中 , 删除布局中的其它元素 ;

将 NavHostFragment 拖入到 布局中 ,
在这里插入图片描述

拖入空间到布局后 , 松开鼠标 , 会弹出如下 " Navigation Graph " 对话框 , 选择要拖入的 NavigationGraph , 然后点击右下角 " OK " 按钮 ;

在这里插入图片描述

拖入后 , 为该空间添加约束 , 最终源码如下 :

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><!--<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" />--><androidx.fragment.app.FragmentContainerViewandroid:id="@+id/fragmentContainerView"android:name="androidx.navigation.fragment.NavHostFragment"android:layout_width="match_parent"android:layout_height="match_parent"app:defaultNavHost="true"app:navGraph="@navigation/my_navigation_graph"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"  /></androidx.constraintlayout.widget.ConstraintLayout>

4、创建菜单


右键点击 res 目录 , 选择 " New / Android Resource File " 选项 ,

在这里插入图片描述

在弹出的 " New Resource File " 对话框中 , 选择 资源类型为 Menu 菜单类型 , 目录名称是 menu , 然后输入 文件名 , 点击 " OK " 按钮 , 创建菜单 ;

在这里插入图片描述

创建完毕后 , 在该菜单配置文件中 , 配置 android:id="@+id/fragmentB" , 其含义是跳转到 NavigationGraph 中 id 为 fragmentB 对应的 Fragment 界面中 , 也就是跳转到 FragmentB 界面 , 触发该菜单选项 , 就会跳转到 FragmentB 界面 ;

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:id="@+id/fragmentB"android:icon="@mipmap/ic_launcher"android:title="跳转到 Fragment B"/>
</menu>

5、Activity 界面开发 NavigationUI 的主要逻辑 ( 重点 )



a、添加 Fragment 布局


在 Activity 的布局文件中 , 添加如下代码 , 不建议在 Design 界面直接拖动 NavHostFragment , 生成的代码报错 , 直接拷贝下面的代码即可 ;

app:navGraph="@navigation/my_navigation_graph" 修改成你自己创建的 NavigationGraph 即可 ;

name 属性必须设置成 android:name="androidx.navigation.fragment.NavHostFragment" 样式的 ;

    <fragmentandroid:id="@+id/fragmentContainerView"android:name="androidx.navigation.fragment.NavHostFragment"android:layout_width="match_parent"android:layout_height="match_parent"app:navGraph="@navigation/my_navigation_graph"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"  />

b、处理 Navigation 导航逻辑 ( 重点 )


首先 , 获取 NavController , 从布局文件中定义的 Fragment 布局中获取 ;

        // 1. 获取 NavControllernavController = Navigation.findNavController(this, R.id.fragmentContainerView)

然后 , 创建 AppBarConfiguration , 这是之后绑定 Navigation 与 AppBar 的重要参数 ;

        // 2. 创建 AppBarConfigurationappBarConfiguration = AppBarConfiguration.Builder(navController.graph).build()

再后 , 将 Navigation 导航 与 AppBar 进行关联 , 关联后 , 就可以使用 菜单 选项进行界面跳转了 ;

        // 3. 将 Navigation 导航 与 AppBar 进行关联NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration)

最后 , 监听 Navigation 页面切换状态 , 如果通过 Navigation 切换了界面 , 会触发 DestinationChangedListener 监听器的 onDestinationChanged 函数 ;

        // 4. 监听页面切换状态navController.addOnDestinationChangedListener{/*相当于重写了下面的函数public fun onDestinationChanged(controller: NavController,destination: NavDestination,arguments: Bundle?)*/navController: NavController, navDestination: NavDestination, bundle: Bundle? ->

c、启用菜单选项


重写 Activity 的 onCreateOptionsMenu 方法 , 加载资源文件中的菜单 ,

此时 只加载菜单 , 此时不能跳转 , 需要重写 onOptionsItemSelected 方法才可以 ;

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {super.onCreateOptionsMenu(menu)// 加载资源文件中的菜单// 只加载菜单 , 此时不能跳转 , 需要重写 onOptionsItemSelected 方法才可以menuInflater.inflate(R.menu.my_menu, menu)return true}

d、使用菜单进行 NavigationUI 导航


只显示菜单是不行的 , 还需要设置菜单的行为 , 重写了该方法 , 菜单选项才能生效 ,

NavigationUI.onNavDestinationSelected(item, navController) 代码的含义是 : 优先使用 NavigationUI 进行导航 ,

如果跳转失败 , 再使用传统的方式执行默认动作 , 代码为 super.onOptionsItemSelected(item) ;

    override fun onOptionsItemSelected(item: MenuItem): Boolean {// 重写了该方法 , 菜单选项才能生效// 优先使用 NavigationUI 进行导航 , 如果跳转失败 , 再使用传统的方式return NavigationUI.onNavDestinationSelected(item, navController)|| super.onOptionsItemSelected(item)}

e、支持导航回退功能


默认状态下通过 Navigation 导航 , 跳转到 FragmentB 后是无法返回的 , 如果想要返回, 需要重写 onSupportNavigateUp 方法 ;

NavigationUI.navigateUp(navController, appBarConfiguration) 的作用就是将 Navigation 导航切换界面 , 记录到回退栈中 ;

    // 默认状态下进入 FragmentB 后是无法返回的// 如果想要返回, 需要重写 onSupportNavigateUp 方法override fun onSupportNavigateUp(): Boolean {return NavigationUI.navigateUp(navController, appBarConfiguration)|| super.onSupportNavigateUp()}




三、完整源码示例 - NavigationUI 类使用




1、Fragment 相关源码



a、FragmentA 界面的 Kotlin 源码和布局文件


FragmentA 基本是默认代码 , 删除了参数传递相关的逻辑 , 显得更加简洁 ;


FragmentA 代码 :

package kim.hsl.app2import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragmentclass FragmentA : Fragment() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {// Inflate the layout for this fragmentreturn inflater.inflate(R.layout.fragment_a, container, false)}
}

布局文件 :

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".FragmentA"><!-- TODO: Update blank fragment layout --><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:text="FragmentA" /></FrameLayout>

b、FragmentB 界面的 Kotlin 源码和布局文件


在该界面中 , 设置了 隐藏 AppBar 中的 菜单按钮 的功能 , 跳转到 FragmentB 之后 , 右上角 就不再显示菜单按钮 ;


FragmentB 代码 :

package kim.hsl.app2import android.os.Bundle
import android.view.*
import androidx.fragment.app.Fragmentclass FragmentB : Fragment() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {// 确保 onCreateOptionsMenu 函数执行setHasOptionsMenu(true)// 为 Fragment 加载布局return inflater.inflate(R.layout.fragment_b, container, false)}override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {// 清空菜单menu.clear()super.onCreateOptionsMenu(menu, inflater)}
}

FragmentB 的布局文件 :

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".FragmentB"><!-- TODO: Update blank fragment layout --><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:text="FragmentB" /></FrameLayout>

2、NavigationGraph 相关源码


在这里配置两个 Fragment , 不需要配置跳转动作 , 只需要在此处定义 Fragment 即可 ;

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/my_navigation_graph"app:startDestination="@id/fragmentA"><fragmentandroid:id="@+id/fragmentA"android:name="kim.hsl.app2.FragmentA"android:label="fragment_a"tools:layout="@layout/fragment_a" /><fragmentandroid:id="@+id/fragmentB"android:name="kim.hsl.app2.FragmentB"android:label="fragment_b"tools:layout="@layout/fragment_b" />
</navigation>

3、MainActivity 主界面相关源码 ( 重点 )


package kim.hsl.app2import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.navigation.NavController
import androidx.navigation.NavDestination
import androidx.navigation.Navigation
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.NavigationUIclass MainActivity : AppCompatActivity() {lateinit var navController: NavControllerlateinit var appBarConfiguration: AppBarConfigurationoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 1. 获取 NavControllernavController = Navigation.findNavController(this, R.id.fragmentContainerView)// 2. 创建 AppBarConfigurationappBarConfiguration = AppBarConfiguration.Builder(navController.graph).build()// 3. 将 Navigation 导航 与 AppBar 进行关联NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration)// 4. 监听页面切换状态navController.addOnDestinationChangedListener{/*相当于重写了下面的函数public fun onDestinationChanged(controller: NavController,destination: NavDestination,arguments: Bundle?)*/navController: NavController, navDestination: NavDestination, bundle: Bundle? ->Log.i("octopus", "OnDestinationChangedListener 监听器中 onDestinationChanged 函数触发")}}override fun onCreateOptionsMenu(menu: Menu?): Boolean {super.onCreateOptionsMenu(menu)// 加载资源文件中的菜单// 只加载菜单 , 此时不能跳转 , 需要重写 onOptionsItemSelected 方法才可以menuInflater.inflate(R.menu.my_menu, menu)return true}override fun onOptionsItemSelected(item: MenuItem): Boolean {// 重写了该方法 , 菜单选项才能生效// 优先使用 NavigationUI 进行导航 , 如果跳转失败 , 再使用传统的方式return NavigationUI.onNavDestinationSelected(item, navController)|| super.onOptionsItemSelected(item)}// 默认状态下进入 FragmentB 后是无法返回的// 如果想要返回, 需要重写 onSupportNavigateUp 方法override fun onSupportNavigateUp(): Boolean {return NavigationUI.navigateUp(navController, appBarConfiguration)|| super.onSupportNavigateUp()}
}

配套的 布局文件 :

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><!--<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" />--><fragmentandroid:id="@+id/fragmentContainerView"android:name="androidx.navigation.fragment.NavHostFragment"android:layout_width="match_parent"android:layout_height="match_parent"app:navGraph="@navigation/my_navigation_graph"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"  /></androidx.constraintlayout.widget.ConstraintLayout>

配套的 menu 布局文件 :

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:id="@+id/fragmentB"android:icon="@mipmap/ic_launcher"android:title="跳转到 Fragment B"/>
</menu>

4、执行结果


进入界面 , 显示默认的 FragmentA ,

在这里插入图片描述

点击右上角菜单栏 , 弹出 " 跳转到 FragmentB " 按钮 , 点击该菜单选项 , 跳转页面 ,

在这里插入图片描述

此时跳转到了 FragmentB 页面 , 并且触发了监听器 ,

在这里插入图片描述

点击回退按钮 , 回到了 FragmentA 界面 , 又触发了监听器 ;

在这里插入图片描述

相关文章:

【Jetpack】Navigation 导航组件 ⑤ ( NavigationUI 类使用 )

文章目录 一、NavigationUI 类简介二、NavigationUI 类使用流程1、创建 Fragment2、创建 NavigationGraph3、Activity 导入 NavHostFragment4、创建菜单5、Activity 界面开发 NavigationUI 的主要逻辑 ( 重点 )a、添加 Fragment 布局b、处理 Navigation 导航逻辑 ( 重点 )c、启…...

基于NAudio实现简单的音乐播放器

《测试.net开源音频库NAudio》介绍了使用NAudio实现音乐播放和录音的基本用法&#xff0c;本文基于NAudio的音乐播放功能实现简单的mp3音乐播放器程序&#xff0c;主要实现以下功能&#xff1a;   1&#xff09;导入文件夹中的mp3音乐文件&#xff0c;直接导入多个mp3音乐文件…...

C++之“00000001“和“\x00\x00\x00\x01“用法区别(一百八十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…...

Java“魂牵”京东店铺所有商品数据接口,京东店铺所有商品API接口,京东API接口申请指南

要通过京东的API获取店铺所有商品数据&#xff0c;您可以使用京东开放平台提供的接口来实现。以下是一种使用Java编程语言实现的示例&#xff0c;展示如何通过京东开放平台API获取整店商品数据&#xff1a; 首先&#xff0c;确保您已注册成为京东开放平台的开发者&#xff0c;…...

vuex详细用法

Vuex是一个专门为Vue.js应用程序开发的状态管理模式。它可以帮助我们在Vue组件之间共享和管理数据&#xff0c;以及实现更好的代码组织和调试。 在Vue.js中&#xff0c;组件之间的数据通信可以通过props和事件来实现。然而&#xff0c;随着应用程序规模的增长&#xff0c;组件…...

微前端-monorepo-无界

文章目录 前言一、微前端二 、monorepo三 、pnpm硬链接软链接&#xff08;符号链接&#xff09;幽灵依赖依赖安装耗时长monorepo项目搭建子模块复用 四、无界接入无界无界预加载无界传参 总结 前言 本文主要记录微前端框架 无界 的使用与理解以及monorepo代码管理方式。 一、微…...

阿里云矢量图标透明背景转换/展示时变为黑色解决方法

下载了一个矢量图标&#xff0c;背景是透明的 上传到minio然后在前端展示&#xff0c;发现透明&#xff08;白色&#xff09;的地方变成黑色了 处理方法&#xff1a;去除透明的底色。使用window的画图程序打开保存一遍&#xff0c;将透明色转为白色 OK...

Linux之Shell(二)

Linux之Shell 函数系统函数basenamedirname 自定义函数 正则表达式入门常规匹配常用特殊字符 文本处理工具cutawk 综合应用案例归档文件发送消息 函数 系统函数 basename 基本语法 basename [string / pathname] [suffix] 功能描述&#xff1a;basename 命令会删掉所有的前缀…...

以太网POE供电浪涌静电防护推荐TVS二极管

POE是一种传输技术&#xff0c;可在以太网电缆上传输电力和数据。1000M千兆以太网POE供电端口广泛用于安防、视频监控以及智能电网等工业系统&#xff0c;以实现系统内的数据、视频传输、流量控制、以及通过总线实现供电。由于工业以太网工作环境非常严酷苛刻&#xff0c;对于以…...

如何在 JavaScript 中查看结构体数组?

调试 JavaScript 代码的最简单方法是使用许多开发人员使用的 console.log()。有时&#xff0c;我们需要了解数组的结构和存储的值以进行调试。以下介绍如何查看结构数组。 JavaScript 的各种方法允许我们检查数组的结构。例如&#xff0c;我们可以知道数组是否包含对象、嵌套数…...

【SpringBoot学习笔记】02.静态资源与首页订制

静态资源 Spring Boot 通过 MVC 的自动配置类 WebMvcAutoConfiguration 为这些 WebJars 前端资源提供了默认映射规则&#xff0c;部分源码如下。 jar包&#xff1a; JAR 文件就是 Java Archive File&#xff0c;顾名思意&#xff0c;它的应用是与 Java 息息相关的&#xff0c;…...

kotlin 转 Java

今天突然想研究下有些kotlin文件转为Java到底长什么样&#xff0c;好方便优化kotlin代码&#xff0c;搞了半天发现一个非常简单的Android Studio或者Intellij idea官方插件Kotlin&#xff0c;Kotlin是插件的名字&#xff0c;真是醉了&#xff1b; 这里以AS为例&#xff0c;使用…...

【Harmony】在Harmony上面可以使用的Android常用的开源库

序言 Harmony开发中&#xff0c;由于不像Android开发经过这么多年的发展&#xff0c;各种类库都是比较完善的&#xff0c;这就导致在Harmony开发中很多Android类库是不能使用的&#xff0c;但是也有一些是可以使用的&#xff0c;下面是我在Harmony开发中实际开发中可以使用的部…...

数学建模:灰色关联分析

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 灰色关联分析法 算法流程 建立一个m行 n列的矩阵 X X X &#xff0c;其中 m 表示评价对象&#xff0c; n表示评价指标首先进行矩阵的归一化&#xff0c;得到归一化后的矩阵 d a t a data data获取参考向…...

nodepad++ 插件的安装

nodepad 插件的安装 一、插件安装二、安装插件&#xff1a;Json Viewer nodepad 有 插件管理功能&#xff0c;其中有格式化json以及可以将json作为树查看的插件&#xff1a; Json Viewer 一、插件安装 1、首先下载最新的notepad 64位【https://notepad-plus.en.softonic.com…...

学习分享:Ubuntu 下使用 Qt 打开串口报错 Permission denied

Ubuntu 下使用 Qt 打开串口报错 Permission denied 错误描述 提前声明一下&#xff0c;开发环境是 Ubuntu18.04&#xff0c;用户是非 root 用户。 因项目需求&#xff0c;需要使用到 Qt 收发串口数据&#xff0c;曾经写过一个串口调试助手的程序 通俗易懂玩QT&#xff1a;串口…...

Javaweb入门

Spring Spring发展到今天已经形成一种开发生态圈&#xff0c;Spring提供若干个子项目&#xff0c;每个项目用于完成特定的功能。 Spring Boot可以帮助我们非常快速的构建应用程序、简化开发、提高效率 SpringBootWeb入门 需求&#xff1a;使用Spring Boot开发一个web应用&a…...

后端开发基础概念

后端开发基础概念 目前处于项目上手阶段&#xff0c;在学习项目过程中&#xff0c;有一些一知半解或者不明白含义的专业名词或者缩写&#xff0c;在此汇总。里面的内容很多都是基于个人理解&#xff0c;水平有限如果有出错的地方还请各位大佬批评指正。 2023年8月31日00:34:22…...

ELK原理和介绍

为什么用到ELK&#xff1a; 一般我们需要进行日志分析场景&#xff1a;直接在日志文件中 grep、awk 就可以获得自己想要的信息。但在规模较大的场景中&#xff0c;此方法效率低下&#xff0c;面临问题包括日志量太大如何归档、文本搜索太慢怎么办、如何多维度查询。需要集中化…...

FBX SDK 开发环境配置 visual studio 2022

FBX | Adaptable File Formats for 3D Animation Software | Autodesk. 下载windows的sdk并安装. 创建一个c console 工程 设置include目录 添加预处理宏 FBX_SHARED1 添加fbx sdk lib 目录 添加依赖lib : libfbxsdk-md.lib libxml2-md.lib zlib-md.lib 配置完毕....

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...