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

在 Flutter 中使用 webview_flutter 4.0 | 基础用法与事件处理

在这里插入图片描述

大家好,我是 17。

Flutter WebView 一共写了四篇文章

  1. 在 Flutter 中使用 webview_flutter 4.0 | 基础用法与事件处理
  2. 在 Flutter 中使用 webview_flutter 4.0 | js 交互
  3. Flutter WebView 性能优化,让 h5 像原生页面一样优秀,已入选 掘金一周 2023.02.22 期
  4. Flutter WebView 如何与 h5 同步登录状态 已入选 CSDN每天值得看–2023-02-21

本文是第 1 篇,定位是新手入门,介绍和演示 webview 的基础用法。最后还介绍了事件处理的技巧。

环境准备已经在 在 Flutter 中使用 webview_flutter 4.0 | js 交互 说过了,不再赘述。既然是新手入门,就会本着详尽的原则,而且会多配示例。

获取页面信息

获取页面 title

核心方法:controller.getTitle

完整示例,放在 main.dart 就能运行。运行示例,点击获取 title 的按钮,会在控制台显示:CSDN - 专业开发者社区

使用 WebView_flutter 4.0 主要分三步

  1. 声明 WebViewController
  2. 在 initState 中初始化 controller
  3. 把 controller 赋值给 WebViewWidget,WebViewWidget 显示页面。
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';void main() {runApp(const MyApp());
}class MyApp extends StatefulWidget {const MyApp({super.key});State<MyApp> createState() => _MyAppState();
}class _MyAppState extends State<MyApp> {// 1late WebViewController controller;void initState() {// 2controller = WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted)..loadRequest(Uri.parse('https://www.csdn.net/'));super.initState();}Widget build(BuildContext context) {return MaterialApp(home: Scaffold(body: Column(children: [// 3Expanded(child: WebViewWidget(controller: controller))],),floatingActionButton: ElevatedButton(onPressed: () async {var title = await controller.getTitle();print(title);},child: Text('获取 title'),)));}
}

页面信息相关的还有另外三个方法:

  • currentUrl 获取页面的 url
  • reload 重新加载当前 url
  • setUserAgent 设置页面 userAgent

userAgent 用来标识身份。具体怎么写自己定,但要有一个特殊的标识用作区分。比如微信的标识是 MicroMessenger。

滚动页面

  • scrollBy 相对原位置滚动
  • scrollTo 滚动到绝对位置

比如现在滚动位置在 0 0,scrollBy(0,100) 执行一次向下滚动 100,执行两次向下滚动 200。scrollTo(0,100) 执行一次向下滚动 100,执行两次不动,还是在 0 100 的位置。

用 getScrollPosition 可以获得页面当前滚动位置。

这三个都是 controller 的方法和前面提到的 controller.getTitle 的用法是一样的。

虽然 controller 给出了三个方法,但还是略显不够。比如我想让页面向上滚动一半怎么办?还是得靠万能的 js 先获取页面的高度。

floatingActionButton: ElevatedButton(onPressed: () async {var height = await controller.runJavaScriptReturningResult('document.scrollingElement.scrollHeight') as int;var scrollTo = height ~/ 2;controller.scrollTo(0, scrollTo);},child: Text('滚动一半内容'),)));

当然了,可能无滚动真正滚动一半内容,这个示例只是为了说明用 controller 的方法不能完成滚动任务时,可以用万能的 js。

WebView 的导航

  • canGoForward
  • canGoBack
  • goForward
  • goBack

前两个判断是否能前进与后退,后两个执行前进与后退。还是比较简单的。这四个都是 controller 上的方法,看名字就知道含意了。

页面来源

通过 url 获取页面

最简单的情况,只提供 URI 就行了。

var controller = WebViewController();
loadRequest(Uri.parse('https://www.csdn.net/');

可能你还想加上自定义 header,用来提供额外的信息。header 的格式:

{"key1":"value1","key2":"value2",
}

key 要如何写呢?最初,推荐自定义headers 以 X- 开头,但是这种用法被 IETF 在 2012 年 6 月发布的 RFC 6648 明确弃用,原因是其会在非标准字段成为标准时造成不便。所以对于自定义 header 的key,直接命名就行。key 不区分大小写。 如果是多个词,中间用连字符隔开。

controller.loadRequest(Uri.parse('https://www.csdn.net/'),headers: {"Custom-Name":"IAM17"
});

如果内容过多,需要通过 body 发送。但一看 body 的参数类型傻眼了,是 Uint8List,这是什么鬼?

Uint8List 是 8 位无符号整数的固定长度列表。对于长列表,此实现比默认的 List 实现更节省空间和时间。我们理解成用 Uint8List 更高效就行了。那么如何把 String 转成 Uint8List 呢?

分两步

  1. 把 String 转成 List<int>
  2. List<int> 转成 unit8List
import 'dart:typed_data';
Uint8List toUint8List(String str) {final List<int> codeUnits = str.codeUnits;final unit8List = Uint8List.fromList(codeUnits);return unit8List;
}

我们综合起来,把参数都用上。注意:当 body 不为空的时候,method 必须为 LoadRequestMethod.post。

controller.loadRequest(Uri.parse('https://www.csdn.net/'),headers: {"Custom-Name": "IAM17",},method: LoadRequestMethod.post,body: toUint8List("我们见过的!"));

如果想要测试,可以把域名换成你自己的域名。在服务端就可以收到 header “Custom-Name”: “IAM17” 和 body “我们见过的!”

直接把 String 作为页面内容

 controller.loadHtmlString('<a href="/frontend">打开前端页面</a>', baseUrl: 'https://www.csdn.net');

用 baseUrl 参数,html 中的链接就可以只写 path 的部分。

示例中的代码虽然也能运行,但还是建议要写完整的 html。

html 内容存在文件中

import 'dart:io';var documentDirectory = await getApplicationDocumentsDirectory();
var filePath = '${documentDirectory.path}/index.html';
var indexFile = File(filePath);
await indexFile.writeAsString('IAM17');controller.loadFile(filePath);

前面四句是在准备文件,示例只写入了 ‘IAM17’,实际上应该写入完整的 html 内容。运行示例能看到字(可能很小),说明运行成功。

html 内容在 Asset 中

实际上 Asset 这种方式也是把内容保存在文件中, 与 loadFile 不同的是 ,Asset 文件是随代码一起打包发布的。

我们来演练一下。

准备 Asset 文件。

在项目根目录下建立文件夹 html,在 html 下建立 index.html 文件,文件里放如下内容

<!DOCTYPE html>
<head>
<title>webview asset demo | IAM17</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no,viewport-fit=cover" />
<style>
body{background:#BBDFFC;  text-align:center;color:#C45F84;padding-top:20px;font-size:22px;
}
</style>
</head>
<html>
<body>
大家好,我是 17
</body>
</html>

注册 Asset

打开 pubspec.yaml 增加下面的内容

 assets:- html/

运行代码

 controller.loadFlutterAsset('html/index.html');

会看到下面的效果

使用 NavigationDelegate

NavigationDelegate 可以拦截页面请求,以及跟踪导航请求的进度。

拦截

虽然前面的文章已经讲过拦截了,但因为这个内容比较重要,也是为了内容完整,这里再说一下。

 controller..setNavigationDelegate(NavigationDelegate(onNavigationRequest: (request) {if (request.url.endsWith('/a.html')) {scheduleMicrotask(() =>controller.loadRequest(Uri.parse('http://localhost:8080/b.html'));return NavigationDecision.prevent;}return NavigationDecision.navigate;},))..loadRequest(Uri.parse('http://localhost:8080'));

逻辑上还是很简单的,根据 url 判断是否需要拦截。对需要拦截的 url 阻止本次请求。可以发起新的请求,也可以什么都不做。

页面加载完成

页面加载完成后,可以在这里运行 js,比如可以在这里拿到 cookie。

NavigationDelegate(onPageFinished: (url) async {var cookie = await controller.runJavaScriptReturningResult('document.cookie') as String;print(cookie);
})

如果你不需要拿到 js 的运行结果,可以用 controller.runJavaScript

有的页面资源很多,加载需要时间,可以用 NavigationDelegate 下面的 onProgress 回调做页面加载动画。

事件处理

在 ListView 中响应手势

默认情况下,WebViewWidget 在 listView 中是无法响应上下滑动的手势的。为了让 WebViewWidget 可以滑动查看 WebView 中的更多内容,需要指定 gestureRecognizers 属性。

ListView(children: [SizedBox(height: 600,child: WebViewWidget(gestureRecognizers: {Factory<VerticalDragGestureRecognizer>(() {return VerticalDragGestureRecognizer()..onStart = (DragStartDetails details) {print("start");}..onDown = (DragDownDetails details) {print("down: $details");};})}, controller: controller),)],
);

看下 gestureRecognizers 属性的类型 Set<Factory<OneSequenceGestureRecognizer>> 可能会吓到一些小伙伴,我们一层一层拆解,其实也是很简单的。

最外层一个是 Set,是为了容纳多个手势,每种类型的手势只能有一个。

这里的 Factory 不同于构造函数那块使用的 factory(注意 f 是小写的)。构造函数前面的 factory 是一个关键字,这里的 Factory 是一个类。

class Factory<T> {const Factory(this.constructor) : assert(constructor != null);final ValueGetter<T> constructor;Type get type => T;String toString() {return 'Factory(type: $type)';}
}

关键在于 constructor,constructor 是 ValueGetter<T> 类型,ValueGetter<T>T Function() 的函数签名。回到 Factory 的构造函数,Factory 需要一个参数,参数的类型是 T Function()。这样就很明了了。现在 T 是 OneSequenceGestureRecognizer ,new 一个 Factory 类的实例,可以这样写:

Factory<VerticalDragGestureRecognizer>(() => VerticalDragGestureRecognizer());

VerticalDragGestureRecognizer 是 OneSequenceGestureRecognizer 的子类。

当然了,这样写也是一样的。

Factory<VerticalDragGestureRecognizer>(() {return VerticalDragGestureRecognizer();
});

把它放到 Set 里,就成了!

{Factory<VerticalDragGestureRecognizer>(() {return VerticalDragGestureRecognizer();})
}

可以对 VerticalDragGestureRecognizer 进行一些初始化化的操作。

{Factory<VerticalDragGestureRecognizer>(() {var recognizer = VerticalDragGestureRecognizer();recognizer.onStart = (DragStartDetails details) {print("start");};recognizer.onDown = (DragDownDetails details) {print("down: $details");};return recognizer;})}

级联 ( … ) 允许您对同一对象进行一系列操作。除了访问实例成员之外,您还可以在同一个对象上调用实例方法。这通常可以节省您创建临时变量的步骤,并允许您编写更流畅的代码。

本例中我们对 recognizer 连续进行了属性赋值,可以用级联简化代码,省掉中间变量 recognizer。

 {Factory<VerticalDragGestureRecognizer>(() {return VerticalDragGestureRecognizer()..onStart = (DragStartDetails details) {print("start");}..onDown = (DragDownDetails details) {print("down: $details");};})}

在其它滚动 widget 中也可以同样的方式让 webview 响应手势。

当有 widget 遮盖住 VebView,如何让事件穿透

这部分是附加的,跳过不会影响 WebView 的使用。

有时候,需要在 WebView 上浮动一些自己的 widget。在 Stack 中把这些 widget 放在 WebView 的后面就可以了,效果上 这些 widget 覆盖在 WebView 的上面。

在下面的示例中是一个半透明的绿色方块。点击这个绿色方块的时候,事件是不能穿透到 WebView 上面的。现在的需求是想让事件穿透到 WebView 上。

MaterialApp(home: Scaffold(body: SafeArea(child: Stack(children: [WebViewWidget(controller: controller),Positioned(top: 100,left: 0,right:0,child: Container(color: Color.fromRGBO(0, 250, 0, .3), height: 300,)),],)

实现在的方案也是很简单的,用 IgnorePointer 把 container 包起来就行了。

 Stack(children: [WebViewWidget(controller: controller),Positioned(top: 100,left: 0,right: 0,child: IgnorePointer(child: Container(color: Color.fromRGBO(0, 250, 0, .3),height: 300,))),],)

原理解析

简单来说,一个 Widget 要响应事件,需要先通过 HitTest。一个 Widget 有多个 child 的时候,只要有一个 child 通过点击测试,就可以响应事件。从后向前判断每一个 child 是否通过 HitTest, 后面的 child 测试通过,就不会再判断前面的 chid。

没有 IgnorePointer 的时候,Container HitTest 通过,WebViewWidget 没机会参与测试,当然也就没机会响应事件了。

加上 IgnorePointer 导致 Container HitTest 不通过,接着判断前面的 child WebViewWidget,WebViewWidget HitTest 通过,所以可以响应事件了。

关于事件的更多内容请参见

  • 【交互 widget】Flutter Listener
  • 【交互 widget】IgnorePointer 与 AbsorbPointer

到这里,WebView 的文章就全部结束了。 WebView 方面如果还有哪里没提到的,欢迎小伙伴们提出来,17 再补充。

番外

上周发了 Flutter WebView 如何与 h5 同步登录状态 后,收到系统通知,上榜了

CSDN每天值得看–2023-02-21

收到这个通知心中无比喜悦,自己的文章得到了官方认可!一个多月来写文的疲惫感一扫而空。

发完三篇 WebView 的文章后,总感觉有什么东西没提到。一想到下次再写 WebView 不知是何年月,我决定立即补上这篇新手入门的文章。

整花了一个月的时间,WebView 的文章终于齐整了。 写文花费的精力很大,自从节后复工以来,17 周末都没出过门,一心写文。17 自己都奇怪哪来这么大的劲头?原因是 小伙伴们的支持。只要小伙伴们支持我,17 就有动力写下去。

相关文章:

在 Flutter 中使用 webview_flutter 4.0 | 基础用法与事件处理

大家好&#xff0c;我是 17。 Flutter WebView 一共写了四篇文章 在 Flutter 中使用 webview_flutter 4.0 | 基础用法与事件处理在 Flutter 中使用 webview_flutter 4.0 | js 交互Flutter WebView 性能优化&#xff0c;让 h5 像原生页面一样优秀&#xff0c;已入选 掘金一周 …...

JavaWeb--Servlet

Servlet1 简介2 快速入门3 执行流程4 生命周期5 方法介绍6 体系结构7 urlPattern配置8 XML配置目标&#xff1a; 理解Servlet的执行流程和生命周期掌握Servlet的使用和相关配置 1 简介 Servlet是JavaWeb最为核心的内容&#xff0c;它是Java提供的一门动态web资源开发技术。 使…...

Linux启动过程

theme: channing-cyan 两种启动方式 传统启动方式&#xff08;LEGACYMBR&#xff09; 指传统BIOS启动方式&#xff0c;存在一些不足&#xff1a;比如最大只支持2TB磁盘&#xff0c;磁盘最多四个分区&#xff0c;且不支持图形操作 UEFIGPT方式 是新式的启动方式&#xff0c…...

面试资料整理——C++

C/C难题的高赞回答「中文版」 https://mp.weixin.qq.com/s/KBEnrRVb1T6LfwHgaB4jiQ C/C难题的高赞回答「中文版」&#xff0c;帮你整理好了 https://mp.weixin.qq.com/s/o9MdENiasolVT-Fllag2_Q C语言与C面试知识总结 https://mp.weixin.qq.com/s/MGSoPqPv_OzyWBS5ZdnZgw 程…...

【ArcGIS Pro二次开发】(9):GeoProcessing工具和自定义工具的调用

ArcGIS Pro自带了1000种以上的GeoProcessing工具&#xff0c;几乎可以实现所有你想要做的事。 ArcGIS Pro的二次开发并不需要我们从底层做起&#xff0c;很多功能只要学会调用工具并组合使用&#xff0c;就完全可以实现。 下面介绍如何调用系统自带的GeoProcessing工具&#x…...

皕杰报表斜线单元格、图表里或导出pdf的中文显示小方块解决方案

在皕杰报表中&#xff0c;如果含有斜线的单元格、统计图的报表、或导出pdf时&#xff0c;汉字变成小方框&#xff0c;这往往是服务器端操作系统的中文安装包没有装全&#xff0c;导致报表里用到的字体在服务器端的操作系统里找不到&#xff0c;因此成了小方块。因为斜线单元格里…...

python读写hdfs文件的实用解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…...

RK3399+FPGA+MIPI 方案细节之subLVDS to MIPI处理

#CROSSLINK系列 #CROSSLINK vs XO3L 总的来说XO3L的灵活性更强&#xff0c;更近似于一片通用的CPLD&#xff1b;CROSSLINK专用性更强。 针对subLVDS转换到MIPI的需求&#xff0c;CROSSLINK比较有优势&#xff0c;因为集成度更高&#xff0c;所以稳定性也更高。 #要点 #crossl…...

Vue组件是怎样挂载的

我们先来关注一下$mount是实现什么功能的吧&#xff1a; 我们打开源码路径core/instance/init.js: export function initMixin (Vue: Class<Component>) {......initLifecycle(vm)// 事件监听初始化initEvents(vm)initRender(vm)callHook(vm, beforeCreate)initInject…...

gcc: 编译选项:-fdelete-null-pointer-checks、-fno-delete-null-pointer-checks

文章目录 说明实例:Linux 里的使用chatGPT说明 这个说明写的有些理解不了,可能还是不太理解(有未知的东西在里面?)。但是从这个编译选项的命名上来看还是非常明确,就是删除不必要的空指针检查。使用时要小心了,这个优化超出了编译的界限! -fdelete-null-pointer-check…...

周赛334(前缀和、贪心+双指针、Dijkstra求最短路径、二分答案)

文章目录[6369. 左右元素和的差值](https://leetcode.cn/problems/left-and-right-sum-differences/)前缀和[6368. 找出字符串的可整除数组](https://leetcode.cn/problems/find-the-divisibility-array-of-a-string/)超长整数如何取余&#xff1f;[6367. 求出最多标记下标](ht…...

imx6ull——I2C驱动

I2C基本介绍 SCL 为高电平&#xff0c;SDA 出现下降沿:起始位 SCL 位高电平&#xff0c;SDA出现上升沿:停止位 主机——从机地址&#xff08;ack&#xff09;——寄存器地址&#xff08;ack&#xff09;——数据&#xff08;ack&#xff09; 重点&#xff1a;先是写&#xff0c…...

Spring Cache的基本使用与分析

概述 使用 Spring Cache 可以极大的简化我们对数据的缓存&#xff0c;并且它封装了多种缓存&#xff0c;本文基于 redis 来说明。 基本使用 1、所需依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-…...

【安全知识】——端口复用隐藏后门

作者名&#xff1a;白昼安全主页面链接&#xff1a; 主页传送门创作初心&#xff1a; 以后赚大钱座右铭&#xff1a; 不要让时代的悲哀成为你的悲哀专研方向&#xff1a; web安全&#xff0c;后渗透技术每日鸡汤&#xff1a; 精彩的人生是在有限的生命中实现无限价值端口复用是…...

Tina_Linux量产测试使用指南_new

OpenRemoved_Tina_Linux_量产测试_使用指南_new 1 概述 文档主要描述如何配置tinatest 并搭建量产测试环境。 1.1 编写目的 • 介绍量产配置方法&#xff1b; • 介绍量产测试环境搭建流程&#xff1b; • 介绍如何使用dragonMAT 软件&#xff1b; • 方便开发人员按照说明…...

STC32单片机 普通 I/O 口中断功能介绍和使用

STC32单片机 普通 I/O 口中断功能和使用✨STC32单片机普通 I/O 口中断&#xff0c;不是传统外部中断. &#x1f516;手册上描述&#xff1a;STC32G 系列支持所有的 I/O 中断&#xff0c;且支持 4 种中断模式&#xff1a;下降沿中断、上升沿中断、低电平中断、高电平中断。每组 …...

计算机学生如何找到第一份实习?

作为一名计算机专业的学生&#xff0c;找到第一份实习是非常重要的一步&#xff0c;它不仅可以帮助你更好地了解行业&#xff0c;增加实践经验&#xff0c;还可以为即将到来的校招提供有力支持。计算机专业的校招&#xff0c;每年都在变得越来越卷。5年前&#xff0c;可能你只要…...

《Python机器学习》基础代码

1&#xff0c;要学习Python机器学习,第一步就是读入数据,这里我们以读入excel的数据为例,利用jupyter notebook来编码,具体教程看这个视频 推荐先上传到jupyter notebook,再用名字.xlsx来导入 Jupyter notebook导入Excel数据的两种方法介绍_哔哩哔哩_bilibili 2&#xff0c;…...

【前端】JS异步加载

文章目录为什么要异步加载如何实现异步加载参考为什么要异步加载 两个原因其实是一个意思。 原因1&#xff1a; JS是单线程的语言&#xff0c;它会同步的执行代码&#xff0c;从上往下执行 但是&#xff0c;一旦网络不好&#xff0c;或要加载的js文件过大的话&#xff0c;会…...

【MySQL】SQL语言的五个部分

DQL 数据查询语言&#xff08;Data Query Language&#xff0c;DQL&#xff09;&#xff1a;DQL主要用于数据的查询&#xff0c;其基本结构是使用SELECT子句&#xff0c;FROM子句和WHERE子句的组合来查询一条或多条数据。 DML 数据操作语言&#xff08;Data Manipulation La…...

详细的IO面试题汇总

IO 流简介 IO 即 Input/Output&#xff0c;输入和输出。数据输入到计算机内存的过程即输入&#xff0c;反之输出到外部存储&#xff08;比如数据库&#xff0c;文件&#xff0c;远程主机&#xff09;的过程即输出。数据传输过程类似于水流&#xff0c;因此称为 IO 流。IO 流在…...

在Linux终端管理你的密码!

大家好&#xff0c;我是良许。 现在是互联网时代&#xff0c;我们每天都要跟各种 APP 、网站打交道&#xff0c;而这些东西基本上都需要注册才可以使用。 但是账号一多&#xff0c;我们自己都经常记不清对应的密码了。有些小伙伴就一把梭&#xff0c;所有的账号密码都是一样。…...

【设计模式】策略模式在Java工程中应用

在之前的文章中&#xff0c;曾经给大家介绍过策略模式&#xff1a;【设计模式】策略模式&#xff0c;在该篇文章中&#xff0c;我们曾很清楚的说到&#xff0c;策略模式主要解决的问题是&#xff1a;在有多种算法相似的情况下&#xff0c;解决使用 if...else 所带来的复杂和难以…...

Linux驱动开发工程师需要掌握哪些技能?

一、前言 Linux驱动开发是一项高度技术性的工作&#xff0c;需要深厚的编程技能和对计算机硬件的深入理解。随着物联网、人工智能等领域的快速发展&#xff0c;Linux驱动开发工程师的需求日益增加。在这篇文章中&#xff0c;我将为您介绍一条Linux驱动开发工程师的学习路线&am…...

【人脸识别】FROM:提升遮挡状态下的人脸识别效果

论文题目&#xff1a;《End2End Occluded Face Recognition by Masking Corrupted Features》 论文地址&#xff1a;https://arxiv.org/pdf/2108.09468v3.pdf 代码地址&#xff1a;https://github.com/haibo-qiu/from 1.前言 人脸识别技术已经取得了显著的进展&#xff0c;主要…...

浏览器缓存

什么是缓存? 当第一次访问网站的时候,比如www.baidu.com,电脑会图片,文件等下载下来,当第二次访问网站的时候,网站就会直接被加载出来. 缓存的好处? 减轻服务器压力,减少请求的放松.提高性能,在本地打开资源肯定比在服务器上获取要快减少宽带的消耗,当我们使用缓存时,只会…...

【软考 系统架构设计师】论文范文③ 论数据访问层设计技术及其应用

>>回到总目录<< 文章目录 论数据访问层设计技术及其应用范文摘要正文论数据访问层设计技术及其应用 在信息系统的开发与建设中,分层设计是一种常见的架构设计方法,区分层次的目的是为了实现“高内聚低耦合”的思想。分层设计能有效简化系统复杂性,使设计结构清…...

802.11 MCS 的最低SNR分析

常常看到这样的表格: 那么这个SNR如何而来? 看看RSSI和SNR的关系,它们之间隔了一个noise floor。从表格看得出,这个底噪在-80~-90之间。 而SNR的核心,也有类似的原因,它和BER有关。...

用于C++的对象关系映射库—YB.ORM

1 介绍YB.ORM YB.ORM 旨在简化与关系数据库交互的 C 应用程序的开发。 对象关系映射器(ORM) 通过将数据库表映射到类并将表行映射到应用程序中的对象来工作&#xff0c;这种方法可能不是对每个数据库应用程序都是最佳的&#xff0c;但它被证明在需要复杂逻辑和事务处理的应用程…...

Cesium 100K数据加载 支持弹窗 动态更改位置

前言&#xff1a;今天总结关于point、label、billboard海量数据加载。后续会研究下大量model加载以及大bim(几百G上T)模型记载 海量点加载 弹窗 加载点位时&#xff0c;不加载弹窗。点击点位时在加载弹窗&#xff0c;及有效的减少加载量&#xff0c;优化性能。 const handler …...

网站开发需求分析word/免费网站友情链接

之前已经写过一篇关于Lucene安装学习的文章&#xff1a;http://www.cnblogs.com/charlesblc/p/5980525.html 还有一篇关于Solr安装使用的文章&#xff1a;http://www.cnblogs.com/charlesblc/p/5981292.html 上面两篇比较偏实践和应用&#xff0c;开了个头&#xff1b;这一篇是…...

上海建设网站找哪家/爱站网关键词工具

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 N1叉车司机考试总结考前必练&#xff01;安全生产模拟考试一点通每个月更新N1叉车司机模拟考试题库题目及答案&#xff01;多做几遍&#xff0c;其实通过N1叉车司机复审模拟考试很简单。 1、【多选题】汽油的主要成分…...

汕头企业网站推广技巧/线上职业技能培训平台

我刚在我的新Digital Ocean Cent OS 7 x64服​​务器上安装了Apache.在遵循Digital Ocean的教程时,yum无法安装mysql-server.# yum install mysql mysql-server mysql-libs mysql-serverLoaded plugins: fastestmirrorLoading mirror speeds from cached hostfile* base: mirro…...

做网站模板在哪儿找/seo含义

1.定义 Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory method let a class defer instantiation to subclasses.(定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟…...

xml网站地图格式/seo搜索引擎入门教程

题目描述 Description有一个NM的单位方格中&#xff0c;其中有些方格是水塘&#xff0c;其他方格是陆地。如果要用12的矩阵区覆盖&#xff08;覆盖过程不容许有任何部分重叠&#xff09;这个陆地&#xff0c;那么最多可以覆盖多少陆地面积。 输入描述 Input Description输入文件…...

网站开发视频是存储的/搭建网站基本步骤

对如何写一个工业级的Python项目作一个top-down小结。一、项目结构顶层结构&#xff1a;文件夹&#xff1a;model可以是项目中的自定义类&#xff1b;utils是一些工程工具&#xff0c;比如log&#xff0c;trackerlog存放记录的日志py文件&#xff1a;run&#xff1a;主文件&…...