快速掌握 Flutter 图片开发核心技能
大家好,我是 17。
在 Flutter 中使用图片是最基础能力之一。17 做了精心准备,满满的都是干货!本文介绍如何在 Flutter 中使用图片,尽量详细,示例完整,包会!
使用网络图片
使用网络图片超级简单,直接给出网络地址就行,本例运行后,显示的是一张猫头鹰的图片。
完整代码,贴到 main.dart 就能用。后面的代码只给出 image 相关的。
import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});final imageSrc ='https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/04ec6088c3c544a2b9459582e335483c~tplv-k3u1fbpfcp-watermark.image?';Widget build(BuildContext context) {return MaterialApp(home: Scaffold(body: Center(child: Image.network(imageSrc)),));}
}
图片加载成功后,不管 http 请求头如何,都会被缓存起来,下次请求这个图片会直接从内存中读取。
一般我们需要指定图片的宽度和高度,让它以指定的尺寸显示,避免图片过大撑破布局。
Image.network(imageSrc,width: 100,height: 100,)
如果提供了 cacheWidth 或 cacheHeight,则指示引擎应以指定大小解码图像。无论这些参数如何,图像都将根据约束进行渲染。cacheWidth 和 cacheHeight 主要是为了减少 ImageCache 的内存使用。
cacheWidth 和 cacheHeight 是为了优化内存用的,如果你能确定网络图片的尺寸都是合适的尺寸,就不用设置这两个参数。如果不能保证来源图片的尺寸,比如可能有大尺寸的图片,最好设置这两个参数。这两个参数只能优化内存占用,对下载和解码没有帮助。如果要优化下载,需要把图片缓存在磁盘上,下次直接从磁盘读取,就像 web 缓存那样。
把网络图片缓存到磁盘
我们可以用 cached_network_image 这个插件实现把网络图片缓存到磁盘这个功能。
安装插件
flutter pub add cached_network_image
必须的参数只有一个 imageUrl。
MaterialApp(home: Scaffold(body: Center(child: CachedNetworkImage(imageUrl: imageSrc,)),));
cached_network_image 自带 fadeIn 的效果,在图片加载过程中显示 placeholder,出现错误,显示 errorWidget。
CachedNetworkImage(imageUrl: imageSrc,placeholder: (context, url) => CircularProgressIndicator(),errorWidget: (context, url, error) => Icon(Icons.error),)
有时我们需要把图片应用到其它 widget ,比如用在 BoxDecoration 中,这时需要提供 imageProvider。
CachedNetworkImage(imageUrl: imageSrc,imageBuilder: (context, imageProvider) => Container(decoration: BoxDecoration(image: DecorationImage(image: imageProvider,fit: BoxFit.cover,colorFilter:ColorFilter.mode(Colors.red, BlendMode.colorBurn)),),),placeholder: (context, url) => CircularProgressIndicator(),errorWidget: (context, url, error) => Icon(Icons.error),
),
还有很多参数,可以 在文档中查看
使用 assets 图片
assets 也可以叫做资源。资源是与您的应用程序一起捆绑和部署的文件,可在运行时访问。常见的资源类型包括静态数据(例如 JSON 文件)、配置文件、图标和图像(JPEG、WebP、GIF、动画 WebP/GIF、PNG、BMP 和 WBMP)。
每个资源都由资源文件所在的显式路径(相对于 pubspec.yaml 文件)标识。声明资源的顺序无关紧要。包含资源的目录名称无关紧要。
在构建过程中,Flutter 将资源放入一个名为资源包的特殊存档中,应用程序会在运行时从中读取。
Flutter 使用位于项目根目录的 pubspec.yaml 文件来识别应用程序所需的资源。
资源文件夹的名称是随意的,我们可以把资源文件夹放在和 lib 平级的根目录下面,为图片建立文件夹 images,把上面示例中的猫头鹰图片放入其中。
修改 pubspec.yaml 的配置。
flutter:assets:- images/owl.png
注意空格
在代码中可以通过 images/owl.png
使用图片。
Image.asset('images/owl.png',width: 200,height: 200,
);
运行,成功显示了猫头鹰的图片。当你发布应用程序的时候,pubspec.yaml 中配置的图片会和代码一起打包发布。
如果有很多图片,这样一张一张注册很是麻烦,我们可以直接指定文件夹。比如我们可以一次性注册 images 文件夹下面的所有图片。
flutter:assets:- images/
适配浅色与深色模式
正常情况下,我们用的是浅色模式,在弱光环境下,打开深色模式可获得出色的视觉体验。
构建过程支持资源变体的概念:可以在不同上下文中显示资源的不同版本。当在 pubspec.yaml 中指定资源路径时,构建过程会在相邻子目录中查找任何具有相同名称的文件。然后,此类文件与指定资源一起包含在资源包中。
在 images 下面增加 dark 文件夹,增加在深色模式下使用的与浅色文件同名的图片。17 的电脑屏幕截图:
适配浅色与深色模式的工作就完成了!
images/owl.png 和 images/dark/owl.png 都包含在您的资源包中。前者被视为主要资源,而后者被视为变体。在浅色模式下,Flutter 为我们显示显示 images/owl.png ,在深色模式下显示 images/dark/owl.png。
在不同的设备使用不同分辨率的图片
Flutter 可以根据当前设备像素比加载分辨率合适的图像。
在 image 文件夹下增加 2.0x,3.0x文件夹,放入同名的高分辨率的图片。17 的电脑屏幕的截图:
1.5x 文件夹也是合法的。
适合不同设备分辨率的工作就完成了!
images/2.0x/owl.png 和 images/3.0x/owl.png 都包含在您的资源包中,都被视为变体。
flutter 会自动为我们在 dpr 为 2 的设备上使用 images/2.0x/owl.png 在 dpr 为 3 的设备上使用 images/3.0x/owl.png,在 dpr 为 1 设备上使用 images/owl.png。 images/owl.png 相当于是 images/1.0x/owl.png。
dpr 为设备分辨率(device pixel ratio)英文单词的首字母
还是一样的代码,现在可以适配不同 dpr 的设备!
Image.asset('images/owl.png',width: 200,height: 200,
);
关于设备 dpr 不完全匹配的处理
Flutter 以 dpr 2.0 为界,采用不同的处理方案,目的是为了得到更好的体验。
- 2.0 以下的设备匹配分辨率更高的图片
- 2.0 以上的设备匹配分辨率最接近的图片
比如有一个 dpr 为 1.25 的设备,会采用 2.0 的图片,而不是 1.0的图片。再比如有一个 dpr 为 2.25 的设备,会采用 2.0 的图片,而不会采用 3.0 的图片。
忽略 dpr 信息
如果要忽略 dpr 信息直接读取主资源(就是不带 x.0路径的那个),用 ExactAssetImage。可以指定 scale,默认为 1.0。
如果 scale 为 2.0,则意味着每个逻辑像素对应四个图像像素。看下实际的效果就明白了。
Column(mainAxisSize: MainAxisSize.min,children: [Image(image: ExactAssetImage('images/owl.png', scale: 5)),Image(image: ExactAssetImage('images/owl.png', scale: 10)),],)
scale 越大,图片显示的越小,因为 scale 越大,每个逻辑像素对应的图像像素就越多。
逻辑像素,也叫 设备独立像素(device independent pixels),简称 dip ,与具体设备无关。
使用相册图片
先安装插件
flutter pub add image_picker
使用相册图片需要两步
- 使用 image_picker 插件从相册中读取图片
- 使用 Image.file 展示图片
class MyWidget extends StatefulWidget {const MyWidget({super.key});State<MyWidget> createState() => _MyWidgetState();
}class _MyWidgetState extends State<MyWidget> {final _picker = ImagePicker();File? _file;Widget build(BuildContext context) {return Column(mainAxisAlignment: MainAxisAlignment.center,children: [ElevatedButton(onPressed: () async {var xfile = await _picker.pickImage(source: ImageSource.gallery,maxWidth: 200,maxHeight: 300,requestFullMetadata: false);if (xfile != null) {setState(() {_file = File(xfile.path);});}},child: const Text('从相册中选择图片')),if (_file != null) Image.file(_file!)],);}
}
maxWidth
和 maxHeight
最好设置一下,从源头上控制一下图片的大小,提高效率。如果这里没控制大小,就必须让 Image.file 加上 cacheWidth
,cacheHeight
参数,因为用 Image.file 显示的图片也会缓存起来,需要控制缓存的图片大小,减少内存消耗。
requestFullMetadata: false
是为了避免 ios 闪退。requestFullMetadata: false
表示要请求完整的 metadata,需要在 info.plist( ios / Runner 下面 )中申请权限。
打开 info.plist 的 dict 中加入如下内容就可以了。
<key>NSPhotoLibraryUsageDescription</key>
<string>APP需要您的同意,才能使用相册,以便于上传,发布照片</string>
android 不需要申请权限。
使用相机拍摄的图片
和使用相册图片步骤一样,有两点不同
- source: ImageSource.
gallery修改为source: ImageSource.camera
- 申请相机的权限
android 不需要申请权限,直接可以使用相机,ios 需要 打开 info.plist 在 dict 中加入如下内容
<key>NSCameraUsageDescription</key>
<string>APP需要您的同意,才能使用摄像头,以便于相机拍摄,上传、发布照片</string>
使用内存图片
Image.memory 的必选参数 bytes 是 Uint8List 类型,base64Decode 的返回值正好是 Uint8List,我们用 Image.memory 展示一下 base64 格式的图片。
我们得到的 base64格式的图片可能是这样的
imageString = 'image/jpeg;base64,/9j/4AA...'
把 image/jpeg;base64,
删除,只保留后面的数据,这样才能正常显示。
引用 dart:convert
把 imageString 用 base64Decode
转成 Uint8List 类型,Image.memory 就能显示了。
import 'dart:convert';
Image.memory(base64Decode(imageString));
图片用做装饰
DecoratedBox 是专门用来做装饰的 widget
DecoratedBox(decoration: BoxDecoration(image: DecorationImage(image: AssetImage('images/owl.png')),),child: SizedBox(width: 100,height: 100,),)
更多时候,我们可以用 Container。
Container(width: 100,height: 100,decoration: BoxDecoration(image: DecorationImage(image: AssetImage('images/owl.png'))),)
DecorationImage 的 image 参数类型是 ImageProvider,ImageProvider 的子类都可以用作参数。除了 AssetImage,还可以用 FileImage,MemoryImage,NetworkImage。
图片预加载
在网页中的轮播图中我们一般都会做图片的预加载,用 js 预加载图片,避免图片在轮播时无法显示。Flutter 中也有轮播图,我们也可以做类似的事情。
和 js 预加载一样,Flutter 预加载图片也是很简单的。
preload(BuildContext context) {var configuration = createLocalImageConfiguration(context);for (var src in ['图片地址1', '图片地址2', '图片地址13']) {NetworkImage(src).resolve(configuration);}}
图片什么时候加载完成不用管。Flutter 会用 NetWorkImage 做 key,缓存图片,下次用 NetworkImage 加载同样的图片,无论是否加载完成,都不会再次加载。
resolve
的作用就是把加载的工作提前执行。
判断两个 NetWorkImage 相同,需要 url,scale 都相同,所以如果如果 scale 不同,会触发重新加载。
bool operator ==(Object other) {if (other.runtimeType != runtimeType) {return false;}return other is NetworkImage&& other.url == url&& other.scale == scale;}
centerSlice
centerSlice 用来切 9图的。比如下面这张图片,我们用 9 图的方式来切图。
这张图是300 x 300 的图,把它显示成 400 x 400。我们把它分成 9 个区域。
- 区域 5 会被垂直水平拉伸
- 区域 4,6 被垂直拉伸
- 区域 2,8 被水平拉伸
- 1,3,7,9 保持原样
Column(mainAxisSize: MainAxisSize.min,children: [Image.asset("images/btn.png",width: 300,height: 300,fit: BoxFit.fill,),Image.asset("images/btn.png",centerSlice: Rect.fromLTRB(100, 100, 200,200),width: 400,height:400,scale: 1,)],
);
根据 9 图的特性,我们可以把按钮的背景图做 9 图,用来容纳可变化的字数,也可以把聊天用的气泡做成 9 图。
centerSlice 只能放大,不能缩小。
原图是 300 x 300, centerSlice 处理后的图只能是宽比 300 大,高也比300 大,否则报错。
全局缓存 ImageCache 的设置
ImageCache 有两个属性
- maximumSize 可以获取和设置可以缓存的图片的最大数量,默认 1000 张。
- maximumSizeBytes 可以获取和设置可以缓存的图片的最大容量,默认 100M。
既然这两个属性可以让我们设置,就说明在有的时候,这两个属性的默认值是不合适的。我们可以通过 PaintingBinding.instance.imageCache
拿到全局 ImageCache 的实例,通过PaintingBinding.instance.imageCache.currentSize
监控一下当前已经缓存的图片数量,如果经常达到最大值,说明默认值太小,可以设置的更大些。
maximumSize 设置的数量调高需要考虑到硬件的承受能力。如果硬件条件差,反而会适得其反。这个时候非但不能加大设置,还需要减小设置。
图片类之间的关系
如果只是想会用 Flutter Image,上面的内容就够用了,可以跳过后面的内容。
上面讲了很多,都是零散的,涉及到的类很多,难免有混乱之感,所以需要对他们之间的关系梳理一下。
Image widget 是直接给我们用的。抛开那些命名构造函数,如果我们直接用 Image,只有一个必须的参数 image,image 类型是 ImageProvider。
ImageProvider
abstract class ImageProvider<T> {ImageStream resolve(ImageConfiguration configuration) {// 省略}Future<bool> evict({ ImageCache cache,ImageConfiguration configuration = ImageConfiguration.empty }) async {// 省略}Future<T> obtainKey(ImageConfiguration configuration); ImageStreamCompleter load(T key); // 需子类实现
}
obtainKey(ImageConfiguration) 方法
该接口主要是为了配合实现图片缓存,不同的 key 代表不同的图片数据缓存。ImageProvider 从数据源加载完数据后,会在全局的 ImageCache 中缓存图片。
resolve(ImageConfiguration) 方法
ImageStream resolve(ImageConfiguration configuration) {... //省略final ImageStream stream = ImageStream();T obtainedKey; ////定义错误处理函数Future<void> handleError(dynamic exception, StackTrace stack) async {... //省略stream.setCompleter(imageCompleter);imageCompleter.setError(...);}// 创建一个新Zone,为了当发生错误时不会干扰 MainZonefinal Zone dangerZone = Zone.current.fork(...);dangerZone.runGuarded(() {Future<T> key;// 先验证是否已经有缓存try {// 生成缓存key,后面会根据此key来检测是否有缓存key = obtainKey(configuration);} catch (error, stackTrace) {handleError(error, stackTrace);return;}key.then<void>((T key) {obtainedKey = key;// 缓存的处理逻辑final ImageStreamCompleter completer = PaintingBinding.instance.imageCache.putIfAbsent(key, () => load(key), onError: handleError);if (completer != null) {stream.setCompleter(completer);}}).catchError(handleError);});return stream;
}
resolve 是 ImageProvider 对外暴露的主要方法,我们可以调用这个方法来加载图片,Image Widget 也是调用这个方法加载图片。
要从 ImageProvider 获取 ImageStream,调用 resolve 并向其传递一个 ImageConfiguration 对象。
ImageProvider 通过 obtainKey 获得 Key 并使用全局的 imageCache 缓存图片。
类型参数 T 是用于表示已解析配置的对象的类型。这也是图像缓存中用于键的类型。它应该是不可变的并实现 == 运算符和 hashCode getter。
AssetBundleImageProvider,FileImage,MemoryImage,NetworkImage
这四个都是 ImageProvider 的子类,AssetBundleImageProvider 又有两个子类,AssetImage 和 ExactAssetImage,这两个和 FileImage,MemoryImage,NetworkImage 都可以直接给 image 参数赋值。
比如我们要读取 owl.png
Image(image: AssetImage("image/owl.png"),);Image.asset("image/owl.png");
这两种都能显示 owl.png。那么有什么区别呢?我们看下 Image.asset 构造函数的源码
Image.asset(String name, {省略...}) : image = ResizeImage.resizeIfNeeded(cacheWidth,cacheHeight,scale != null? ExactAssetImage(name, bundle: bundle, scale: scale, package: package): AssetImage(name, bundle: bundle, package: package),),省略...;
Image.asset 构造函数为我们创建了 ImageProvider。
- 如果 scale 不为空,创建 ExactAssetImage,否则创建 AssetImage
- 用 ResizeImage.resizeIfNeeded 包起来。
ResizeImage.resizeIfNeeded 执行下面的逻辑:如果 cacheWidth,cacheHeight 同时为空,直接返回原 ImageProvider,否则返回 ResizeImage。
static ImageProvider<Object> resizeIfNeeded(int? cacheWidth, int? cacheHeight, ImageProvider<Object> provider) {if (cacheWidth != null || cacheHeight != null) {return ResizeImage(provider, width: cacheWidth, height: cacheHeight);}return provider;
}
ResizeImage 在放进缓存之前,会根据 cacheWidth,cacheHeight 对图片做优化,这对于减少内存开销有帮助。
从以上可以看出,没有特殊需要,我们都使用 Image.asset、Image.network、Image.file、age.memory
,这四个命名构造函数。
ImageProvider 的子类还有一个 ScrollAwareImageProvider, RawImage 会调用他避免在快速滚动时加载图像。我们一般不需要直接使用他。
本文到这里就结束了,谢谢观看!
相关文章:
快速掌握 Flutter 图片开发核心技能
大家好,我是 17。 在 Flutter 中使用图片是最基础能力之一。17 做了精心准备,满满的都是干货!本文介绍如何在 Flutter 中使用图片,尽量详细,示例完整,包会! 使用网络图片 使用网络图片超级简…...
复习使用git(二)
删除远程分支 git push origin --delete 分支名 撤销修改 撤销工作区的修改 已修改,但尚未添加(add),使用 git restore 文件名 撤销工作区的修改。 Note: “git checkout – 文件名”,checkout 检出的意思&#x…...
魔兽世界335服务端架设对外网开放的步骤
警告:在没有网络安全防护措施或基础知识的情况下,开放端口可能造成被黑客入侵、流量攻击、破坏数据、资料泄露等情况的发生。在你选择开放端口时,视为已经充分了解可能发生的后果、危害,清楚自己在做什么,并且自己将对…...
华为OD机试模拟题 用 C++ 实现 - 通信误码(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明通信误码题目输入输出示例一输入输出说明示例二输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,...
Vue 核心
文章目录Vue 核心一,Vue 简介(一)官网(二)介绍与描述(三)Vue 的特点(四)与其它 JS 框架的关联(五)Vue 周边库二,初识 Vue三࿰…...
Kylin V10桌面版arm3568 源码安装redis
上传redis-5.0.14.tar.gz到/home/kylin/下载;解压kylinkylin:~/下载$ tar -zxvf redis-5.0.14.tar.gz/opt下新建redis目录,并将上面解压的文件夹移到此处kylinkylin:~/下载$ sudo mv redis-5.0.14 /opt/redis/编译:kylinkylin:/opt/redis/red…...
【ICCV2022】 CAPAO:一种高效的单阶段人体姿态估计模型
CAPAO:一种高效的单阶段人体姿态估计模型 重新思考关键点表示:将关键点和姿态建模作为多人姿态估计的对象(Rethinking Keypoint Representations: Modeling Keypoints and Poses as Objects for Multi-Person Human Pose Estimation…...
ROS1学习笔记:ROS中的坐标管理系统(ubuntu20.04)
参考B站古月居ROS入门21讲:ROS中的坐标系管理系统 基于VMware Ubuntu 20.04 Noetic版本的环境 文章目录一、机器人中的坐标变换二、TF功能包三、小海龟跟随实验3.1 启动实验3.2 查看当前的TF树3.3 坐标相对位置可视化3.3.1 tf_echo3.3.2 rviz一、机器人中的坐标变换…...
requests---(2)session简介与自动写博客
目录:导读 session简介 session登录 自动写博客 获取登录cookies 抓取写博客接口 requests自动写博客 写在最后 http协议是无状态的,也就是每个请求都是独立的。那么登录后的一系列动作,都需要用cookie来验证身份是否是登录状态&#…...
基于 HAProxy + Keepalived 搭建 RabbitMQ 高可用集群
RabbitMQ 集群 通常情况下,在集群中我们把每一个服务称之为一个节点,在 RabbitMQ 集群中,节点类型可以分为两种: 内存节点:元数据存放于内存中。为了重启后能同步数据,内存节点会将磁盘节点的地址存放于磁…...
基于51单片机和proteus的智能调速风扇设计
此智能风扇是基于51单片机和proteus的仿真设计,功能如下: 1. Timer0 PWM控制电机转速 2. DHT11采集温湿度 3. LCD1602显示温湿度及电机状态 4. 按键控制电机加减速启停等 5. 串口控制电机加减速启停等 功能框图如下: Proteus仿真界面如下…...
SQL Server开启CDC的完整操作过程
这里写自定义目录标题写在前面SQL Server开启CDC1. 将指定库的实例先开启CDC2. 开启需要开启CDC的表3. 关闭CDC功能更详细信息参照官网写在前面 鉴于老旧数据的结构和项目都在sqlserver上存储,且迁移成本巨大,当下要为sqlserver的存储过程减负。要将一部…...
【Spring Cloud Alibaba】008-Sentinel
【Spring Cloud Alibaba】008-Sentinel 文章目录【Spring Cloud Alibaba】008-Sentinel一、服务雪崩1、概述2、解决方案常见的容错机制二、Sentinel:分布式系统的流量防卫兵1、**Sentinel** 概述简介特性Sentinel 的开源生态Sentinel 的历史2、Sentinel 基本概念资源…...
解读CRC校验计算
个人随笔 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu) 参考:http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html 参考:https://en.wikipedia.org/wiki/Cyclic_redundancy_check 参考:https://www.cnblogs.com/…...
深入理解Spring MVC下
上一篇博客从理论概念上来梳理Spring MVC相关知识,此篇博客将通过spring官网提供showcase代码为例子,详细介绍showcase代码中包含的各个例子是如何实现的。官网的showcase代码包含的主要例子包括,Demo地址:Mapping Requests&#…...
【Linux】ssh-keygen不需要回车,自动生成密钥,批量免密操作!
使用命令ssh-keygen 需要手动敲击回车,才会生成密钥,如下代码所示 [rootlocalhost ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase):…...
C/C++开发,无可避免的内存管理(篇四)-智能指针备选
一、智能指针 采用C/C开发堆内存管理无论是底层开发还是上层应用,无论是开发新手,还是多年的老手,都会不自觉中招,尤其是那些不是自己一手经历的代码,要追溯问题出在哪里更是个麻烦事。C/C程序常常会遇到程序突然退出&…...
VMware ESXi给虚拟机扩容
用ESXi管理的虚拟机硬盘空间不够了,讲一下如何进行扩容。 一、查看现状 通过如下三个命令,可以查看硬盘情况,可以看到只有500G,已经用了45%。这次我们再扩容500G。 df -Th lsblk fdisk -lIDE磁盘的文件名为 /de…...
认识STM32和如何构建STM32工程
STM32介绍什么是单片机单片机(Single-Chip Microcomputer)是一种集成电路芯片,把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种/0口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电…...
RabbitMQ延迟队列
目录 一、概念 二、使用场景 三、RabbitMQ 中的 TTL (一)队列设置 TTL (二)消息设置 TTL (三)两者的区别 四、整合SpringBoot实现延迟队列 (一)创建项目 (二&am…...
Java中常用的七种队列你了解多少?
文章目录Java中常用的七种队列你了解多少?ArrayBlockingQueue队列如何使用?添加元素到队列获取队列中的元素遍历队列LinkedBlockingQueue队列如何使用?1. 创建SynchronousQueue对象2. 添加元素到队列3. 获取队列中的元素4. 遍历队列SynchronousQueue队列…...
<Java获取时间日期工具类>常见八种场景(一)
一:自定义时间日期工具类常用的八种方式(整理): 0,getTimeSecondNum:时间日期转成秒数,常用于大小比较 1,getLastYearMonthLastDay:获取去年当月最后一天的时间日期 2,getLastYearM…...
接上一篇 对多个模型环形旋转进行优化 指定旋转位置
using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; public class ModelAnimal : MonoBehaviour { //记录鼠标滑动 public Vector2 lastPos;//鼠标上次位置 Vector2 currPos;//鼠标当前位置 Vector2 offset;//两次位置的偏移…...
Unity中获取地形的法线
序之前,生成了地形图:(42条消息) 从灰度图到地形图_averagePerson的博客-CSDN博客那末,地形的法线贴图怎么获取?大概分为两个部分吧,先拿到法线数据,再画到纹理中去。关于法线计算Unity - Scripting API: M…...
模型解释性:PFI、PDP、ICE等包的用法
本篇主要介绍几种其他较常用的模型解释性方法。 1. Permutation Feature Importance(PFI) 1.1 算法原理 置换特征重要性(Permutation Feature Importance)的概念很简单,其衡量特征重要性的方法如下:计算特征改变后模型预测误差的增加。如果打乱该特征的…...
spring常见面试题(2023最新)
目录前言1.spring是什么2.spring的设计核心是什么3.IOC和AOP面试题4.spring的优点和缺点5.spring中bean的作用域6.spring中bean的注入方式7.BeanFactory 和 ApplicationContext有什么区别?8.循环依赖的情况,怎么解决?9.spring中单例Bean是线程…...
华为OD机试题,用 Java 解【压缩报文还原】问题
最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...
机器学习-BM-FKNCN、BM-FKNN等分类器对比实验
目录 一、简介和环境准备 二、算法简介 2.1四种方法类: 2.1.1FKNN 2.1.2FKNCN 2.1.3BM-FKNN 2.1.3BM-FKNCN 2.2数据预处理 2.3输出视图 2.4调用各种方法看准确率 2.4.1BM-FKNCN 2.4.2BM-FKNN 2.4.3FKNCN 2.4.4FKNN 2.4.5KNN 一、简介和环境准备 k…...
ChatGPT火了,对话式人工智能还能干嘛?
身兼数职的ChatGPT 从2022火到了2023 连日来一直是各大平台的热议对象 其实除了写诗、敲代码、处理文档 以ChatGPT为代表的 对话式人工智能 还有更重要的工作要做 对话式AI与聊天机器人 相信大多数人…...
十一、操作数栈的特点(Operand Sstack)
1.每一个独立的栈帧中除了包含局部变量表以外,还包含一个后进先出的操作数栈,也可以称之为表达式栈。 2.操作数栈,在方法执行过程中,根据字节码指令,往栈中写入数据,或提取数据,即入栈ÿ…...
莘县网站建设价格/腾讯控股第三季度营收1401亿
---------------------------------------------------------------OSPF在NBMA网络中的解决方案---------------------------------------------------------------一、OSPF在NBMA网络中产生的通信问题配置基本的帧中继网络帧中继配置R1:interface s1/0ip address 1…...
网站建设管理工作总结报告/软文文案案例
1.Android 5.0 删除ActionBar下面的阴影 于Android 5.0假设你发现的ActionBar下面出现了阴影,例如,下面的设置,以消除阴影: getActionBar().setElevation(0); Android 5.0之前能够用以下代码消除阴影: <item name&q…...
做网站公司cnfg/网络营销模式案例
用户名 性别 邮件{% for user in users %}{{user.name}}{% if user.sex 1 %}男{% else %}女{% endif %}{{user[email]}}{% else %}暂无数据{% endfor %}...
专业网站建设集团/软文广告经典案例分析
vue 兼容IE报错解决方案参考文章: (1)vue 兼容IE报错解决方案 (2)https://www.cnblogs.com/CandyManPing/p/10195377.html 备忘一下。...
网站服务器怎么做/seopc流量排行榜企业
哈喽!大家好,我是小奇,一位热爱分享的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新,可以微信搜索【小奇JAVA面试】第一时间阅…...
网站个人备案步骤/推广网站源码
实现线程安全总结来说存在四种方法:1. 使用ThreadLocal----主要用于数据的传递2. synchronized----JVm来实现的3. lock----cpu的硬件指令4. 使用Atomic类型----使用CPU的指令来实现5. 并发包中读写分离CopyOnWriteArrayList等...6 ......package J…...