flutter学习-day13-功能型组件和状态共享

📚 目录

  1. 导航返回拦截
  2. InheritedWidget数据共享
  3. 跨组件状态共享
    1. 事件总线EventBus
    2. 依赖注入Provider
  4. 颜色和主题
    1. 颜色字符串转成color对象
    2. 颜色亮度
    3. MaterialColor类
    4. 主体
  5. 异步UI更新
    1. FutureBuilder
    2. StreamBuilder
  6. 对话框

本文学习和引用自《Flutter实战·第二版》:作者:杜文

1. 导航返回拦截

为了避免用户误触返回按钮而导致 App 退出,在很多 App 中都拦截了用户点击返回键的按钮,然后进行一些防误触判断,比如当用户在某一个时间段内点击两次时,才会认为用户是要退出。Flutter中可以通过WillPopScope来实现返回按钮拦截。

  • 示例如下:
import 'package:flutter/material.dart';class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => HomePageState();
}class HomePageState extends State<HomePage> {/// 时间DateTime? times;Widget build(BuildContext context) {return WillPopScope(onWillPop: () async {const oneSecond = Duration(seconds: 1);if (times == null || DateTime.now().difference(times!) > oneSecond) {// 两次点击间隔超过1秒则重新计时times = DateTime.now();return false;}return true;},child: Scaffold(appBar: AppBar(title: const Text('Flutter Home'),),body: Center(child: TextButton(child: const Text('点击我'),onPressed: () {},),),),);}
}

2. InheritedWidget数据共享

InheritedWidget提供了一种在 widget 树中从上到下共享数据的方式,比如我们在应用的根 widget 中通过InheritedWidget共享了一个数据,那么我们便可以在任意子widget 中来获取该共享的数据。如Flutter SDK中正是通过 InheritedWidget 来共享应用主题和Locale信息的。如下例子:

  • 计数器使用共享数据
import 'package:flutter/material.dart';class ShareDataWidget extends InheritedWidget {const ShareDataWidget({super.key, required this.data, required Widget child}): super(child: child);final int data;static ShareDataWidget? of(BuildContext context) {return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();}bool updateShouldNotify(ShareDataWidget old) {return old.data != data;}
}class MyTextWidget extends StatefulWidget {const MyTextWidget({super.key});MyTextWidgetState createState() => MyTextWidgetState();
}class MyTextWidgetState extends State<MyTextWidget> {Widget build(BuildContext context) {/// 使用InheritedWidget中的共享数据var txt = ShareDataWidget.of(context)!.data.toString();return Text(txt);}/// 父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。如果build中没有依赖InheritedWidget,则此回调不会被调用。void didChangeDependencies() {super.didChangeDependencies();debugPrint("count修改了");}
}class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => HomePageState();
}class HomePageState extends State<HomePage> {int count = 0;Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Flutter Home'),),body: Center(child: ShareDataWidget(/// 使用ShareDataWidgetdata: count,child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[const Padding(padding: EdgeInsets.only(bottom: 20.0),/// 子widget中依赖ShareDataWidgetchild: MyTextWidget(),),ElevatedButton(child: const Text("点击增加"),/// 每点击一次,将count自增,然后重新build,ShareDataWidget的data将被更新onPressed: () => setState(() => ++count),)],),),),);}
}

2-1. 只引用数据不调用didChangeDependencies

在上面的例子中,如果我们只想在MyTextWidgetState中引用ShareDataWidget数据,但却不希望在ShareDataWidget发生变化时调用MyTextWidgetState的didChangeDependencies()方法,只需要将ShareDataWidget.of()的实现改一下即可。唯一的改动就是获取ShareDataWidget对象的方式,把dependOnInheritedWidgetOfExactType()方法换成了context.getElementForInheritedWidgetOfExactType<ShareDataWidget>().widget。他们的区别就是前者会注册依赖关系,而后者不会。

class ShareDataWidget extends InheritedWidget {const ShareDataWidget({super.key, required this.data, required Widget child}): super(child: child);final int data;static ShareDataWidget? of(BuildContext context) {// return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();return context.getElementForInheritedWidgetOfExactType<ShareDataWidget>()!.widget as ShareDataWidget;}bool updateShouldNotify(ShareDataWidget old) {return old.data != data;}
}

3. 跨组件状态共享

状态管理是一个永恒的话题。如果状态是组件私有的,则应该由组件自己管理;如果状态要跨组件共享,则该状态应该由各个组件共同的父元素来管理。常用的有事件总线EventBus(订阅者模式)和依赖注入Provider(观察者模式)。

3-1. 事件总线EventBus

//订阅者回调签名
typedef void EventCallback(arg);class EventBus {//私有构造函数EventBus._internal();//保存单例static EventBus _singleton = EventBus._internal();//工厂构造函数factory EventBus()=> _singleton;//保存事件订阅者队列,key:事件名(id),value: 对应事件的订阅者队列final _emap = Map<Object, List<EventCallback>?>();//添加订阅者void on(eventName, EventCallback f) {_emap[eventName] ??=  <EventCallback>[];_emap[eventName]!.add(f);}//移除订阅者void off(eventName, [EventCallback? f]) {var list = _emap[eventName];if (eventName == null || list == null) return;if (f == null) {_emap[eventName] = null;} else {list.remove(f);}}//触发事件,事件触发后该事件所有订阅者会被调用void emit(eventName, [arg]) {var list = _emap[eventName];if (list == null) return;int len = list.length - 1;//反向遍历,防止订阅者在回调中移除自身带来的下标错位for (var i = len; i > -1; --i) {list[i](arg);}}
}//定义一个top-level(全局)变量,页面引入该文件后可以直接使用bus
var bus = EventBus();

使用如下:

/// 页面A//监听登录事件
bus.on("login", (arg) {// ......
});/// 页面B// 登录成功后触发登录事件,页面A中订阅者会被调用
bus.emit("login", userInfo);

3-2. 依赖注入Provider

现在Flutter社区已经有很多专门用于状态管理的包了,在此列出几个相对评分比较高的:

名称描述
Provider & Scoped Model两个包都是基于InheritedWidget的,原理相似
ReduxReact生态链中Redux包的Flutter实现
MobXReact生态链中MobX包的Flutter实现
BLoCBLoC模式的Flutter实现

4. 颜色和主题

Flutter里有一个Colors类,里面定义了100多个颜色常量,颜色都是以一个int值保存。而Theme组件可以为Material APP定义主题数据。

4-1. 颜色字符串转成Color对象

  • 颜色固定
/// 直接使用整数值
Color(0xffdc380d)
  • 字符串变量
var c = "dc380d";/// 通过位运算符将Alpha设置为FF
Color(int.parse(c,radix:16)|0xFF000000)/// 通过方法将Alpha设置为FF
Color(int.parse(c,radix:16)).withAlpha(255)

4-2. 颜色亮度

假如要实现一个背景颜色和Title可以自定义的导航栏,并且背景色为深色时我们应该让Title显示为浅色;背景色为浅色时,Title 显示为深色。要实现这个功能,我们就需要来计算背景色的亮度,然后动态来确定Title的颜色。Color 类中提供了一个computeLuminance()方法,它可以返回一个[0-1]的一个值,数字越大颜色就越浅,我们可以根据它来动态确定Title的颜色。

import 'package:flutter/material.dart';/// 定义
class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => HomePageState();
}/// 实现
class HomePageState extends State<HomePage> {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Flutter Home'),),body: const Center(child: Column(children: [NavBar(color: Colors.blue, title: '标题1'),NavBar(color: Colors.white, title: '标题2')],),),);}
}/// 定义组件
class NavBar extends StatelessWidget {final String title;final Color color;const NavBar({super.key,required this.color,required this.title,});Widget build(BuildContext context) {return Container(constraints: const BoxConstraints(minHeight: 52,minWidth: double.infinity,),decoration: BoxDecoration(color: color,boxShadow: const [// 阴影BoxShadow(color: Colors.black26,offset: Offset(0, 3),blurRadius: 3,),],),alignment: Alignment.center,child: Text(title,style: TextStyle(fontWeight: FontWeight.bold,// 根据背景色亮度来确定Title颜色color: color.computeLuminance() < 0.5 ? Colors.white : Colors.black,),));}
}

4-3. MaterialColor类

MaterialColor是实现Material Design中的颜色的类,它包含一种颜色的10个级别的渐变色。它通过"[]"运算符的索引值来代表颜色的深度,有效的索引有:50,100,200,…,900,数字越大,颜色越深。默认值是500。使用方式为Colors.blue.shade50。

  • 例子:
class HomePageState extends State<HomePage> {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Flutter Home'),),body: Center(child: Column(children: [NavBar(color: Colors.blue.shade50, title: '标题1'),NavBar(color: Colors.blue.shade100, title: '标题2'),NavBar(color: Colors.blue.shade200, title: '标题2'),NavBar(color: Colors.blue.shade300, title: '标题2'),NavBar(color: Colors.blue.shade400, title: '标题2'),NavBar(color: Colors.blue.shade500, title: '标题2'),NavBar(color: Colors.blue.shade600, title: '标题2'),NavBar(color: Colors.blue.shade700, title: '标题2'),NavBar(color: Colors.blue.shade800, title: '标题2'),NavBar(color: Colors.blue.shade900, title: '标题2')],),),);}
}

4-4. 主题

ThemeData用于保存是Material 组件库的主题数据,Material组件需要遵守相应的设计规范,而这些规范可自定义部分都定义在ThemeData中了,所以我们可以通过ThemeData来自定义应用主题。在子组件中,我们可以通过Theme.of方法来获取当前的ThemeData。(有些是不能自定义的,比如导航栏高度)。

  • 定义:
ThemeData({Brightness? brightness, // 深色还是浅色MaterialColor? primarySwatch, // 主题颜色样本,见下面介绍Color? primaryColor, // 主色,决定导航栏颜色Color? cardColor, // 卡片颜色Color? dividerColor, // 分割线颜色ButtonThemeData buttonTheme, // 按钮主题Color dialogBackgroundColor,// 对话框背景颜色String fontFamily, // 文字字体TextTheme textTheme,// 字体主题,包括标题、body等文字样式IconThemeData iconTheme, // Icon的默认样式TargetPlatform platform, // 指定平台,应用特定平台控件风格ColorScheme? colorScheme,/// ......
})

下面是一个单个页面换肤的例子,如果想要对整个应用换肤,则可以去修改MaterialApp的theme属性,例子如下:

import 'package:flutter/material.dart';/// 定义
class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => HomePageState();
}/// 实现
class HomePageState extends State<HomePage> {var myThemeColor = Colors.teal;Widget build(BuildContext context) {ThemeData themeData = Theme.of(context);return Theme(data: ThemeData(// 用于导航栏、FloatingActionButton的背景色等primarySwatch: myThemeColor,// 用于Icon颜色iconTheme: IconThemeData(color: myThemeColor),),child: Scaffold(appBar: AppBar(title: const Text('Flutter Home'),),body: Center(child: Column(children: [const Row(mainAxisAlignment: MainAxisAlignment.center,children: [Icon(Icons.favorite),Text(" 颜色跟随主题"),],),Theme(data: themeData.copyWith(iconTheme:themeData.iconTheme.copyWith(color: Colors.black),),child: const Row(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Icon(Icons.favorite),Text(" 颜色固定黑色")]),)],),),floatingActionButton: FloatingActionButton(// 切换主题onPressed: () {setState(() => myThemeColor = myThemeColor == Colors.teal? Colors.blue: Colors.teal);},child: const Icon(Icons.palette))));}
}

5. 异步UI更新

很多时候我们会依赖一些异步数据来动态更新UI,比如在打开一个页面时我们需要先从互联网上获取数据,在获取数据的过程中我们显示一个加载框,等获取到数据时我们再渲染页面;又比如我们想展示文件流、互联网数据接收流的进度。Flutter专门提供了FutureBuilder和StreamBuilder两个组件来快速实现这种功能。

5-1. FutureBuilder

FutureBuilder是Flutter中专门用于异步UI更新的组件,它会依赖一个Future,它会根据所依赖的Future的状态来动态构建自身。

属性描述
futureFutureBuilder依赖的Future,通常是一个异步耗时任务
initialData初始数据,用户设置默认数据
builderWidget构建器,该构建器会在Future执行的不同阶段被多次调用,第一个参数是context
builder.snapshotbuilder的参数,包含当前异步任务的状态信息及结果信息
import 'package:flutter/material.dart';/// 定义
class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => HomePageState();
}/// 实现
class HomePageState extends State<HomePage> {Future<String> mockNetworkData() async {return Future.delayed(const Duration(seconds: 2), () => "我是从互联网上获取的数据");}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Flutter Home'),),body: Center(child: FutureBuilder(future: mockNetworkData(),builder: (BuildContext context, AsyncSnapshot snapshot) {if (snapshot.connectionState == ConnectionState.done) {if (snapshot.hasError) {// 请求失败,显示错误return Text("Error: ${snapshot.error}");} else {// 请求成功,显示数据return Text("Contents: ${snapshot.data}");}} else {// 请求未结束,显示loadingreturn const CircularProgressIndicator();}},),));}
}

5-2. StreamBuilder

StreamBuilder是用于配合Stream来展示流上事件(数据)变化的UI组件。

例子如下:

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';/// 定义
class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => HomePageState();
}/// 实现
class HomePageState extends State<HomePage> {/// 任务流Stream<int> myCounter() {return Stream.periodic(const Duration(seconds: 1), (i) {return i;});}/// 状态文案String str = '';Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Flutter Home'),),body: Center(child: StreamBuilder(stream: myCounter(),builder: (BuildContext context, AsyncSnapshot<int> snapshot) {if (snapshot.hasError) {str = snapshot.error.toString();}switch (snapshot.connectionState) {case ConnectionState.none:str = '没有Stream';case ConnectionState.waiting:str = '等待数据';case ConnectionState.active:str = snapshot.data.toString();case ConnectionState.done:str = '已关闭';}return Text('状态:$str');},),),floatingActionButton: FloatingActionButton(onPressed: () {}, child: const Icon(Icons.palette)));}
}

6. 对话框

对话框本质上也是UI布局,通常一个对话框会包含标题、内容,以及一些操作按钮,为此,Material库中提供了一些现成的对话框组件来用于快速的构建出一个完整的对话框。下面写一个AlertDialog做例子。

构造函数如下:

const AlertDialog({Key? key,this.title, // 对话框标题组件this.titlePadding, // 标题填充this.titleTextStyle, // 标题文本样式this.content, // 对话框内容组件this.contentPadding = const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0), // 内容的填充this.contentTextStyle,// 内容文本样式this.actions, // 对话框操作按钮组this.backgroundColor, // 对话框背景色this.elevation,// 对话框的阴影this.semanticLabel, // 对话框语义化标签(用于读屏软件)this.shape, // 对话框外形
})

使用例子如下:

import 'package:flutter/material.dart';/// 定义
class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => HomePageState();
}/// 实现
class HomePageState extends State<HomePage> {/// 定义对话框Future<bool?> showDeleteConfirmDialog() {return showDialog<bool>(context: context,builder: (context) {return AlertDialog(title: const Text("提示"),content: const Text("您确定要删除当前文件吗?"),actions: <Widget>[TextButton(child: const Text("取消"),onPressed: () => Navigator.of(context).pop(), // 关闭对话框),TextButton(child: const Text("删除"),onPressed: () {//关闭对话框并返回trueNavigator.of(context).pop(true);},),],);},);}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Flutter Home'),),body: const Center(child: Text('点击此处'),),floatingActionButton: FloatingActionButton(onPressed: () async {bool? deleteDialog = await showDeleteConfirmDialog();if (deleteDialog == null) {debugPrint("取消");} else {debugPrint("确认");}}, child: const Icon(Icons.palette)));}
}

本次分享就到这儿啦,我是鹏多多,如果您看了觉得有帮助,欢迎评论,关注,点赞,转发,我们下次见~

往期文章

  • 手把手教你搭建规范的团队vue项目,包含commitlint,eslint,prettier,husky,commitizen等等
  • Web Woeker和Shared Worker的使用以及案例
  • Vue2全家桶+Element搭建的PC端在线音乐网站
  • vue3+element-plus配置cdn
  • 助你上手Vue3全家桶之Vue3教程
  • 助你上手Vue3全家桶之VueX4教程
  • 助你上手Vue3全家桶之Vue-Router4教程
  • 超详细!Vue的九种通信方式
  • 超详细!Vuex手把手教程
  • 使用nvm管理node.js版本以及更换npm淘宝镜像源
  • vue中利用.env文件存储全局环境变量,以及配置vue启动和打包命令
  • 超详细!Vue-Router手把手教程

个人主页

  • CSDN
  • GitHub
  • 简书
  • 博客园
  • 掘金

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/229544.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第3章 多模型思维

目录 1. 孔多塞陪审团定理和多样性预测定理2. 分类模型3. 适当的模型粒度4. 一对多更高的幂超级油轮身体质量指数代谢率女性CEO 5. 多模型思维 1. 孔多塞陪审团定理和多样性预测定理 孔多塞陪审团定理&#xff08;Condorcet jury theorem&#xff09; 从一个解释多数规则长处的…

小程序开发使用vant库

初始化项目步骤就不做阐述。 第一步&#xff1a;安装依赖 vant/weapp npm下载命令&#xff1a;npm i vant/weapp -S --production npm下载命令&#xff1a;yarn add vant/weapp -S --production 第二步 &#xff1a;修改配置 1、找到miniprogram文件下的app.json 将 app.j…

小程序中的合法域名的作用及条件有哪些?

小程序的合法域名是指小程序项目中使用的各种接口、资源文件等所在的域名。在小程序开发中&#xff0c;需要将这些域名添加到小程序后台的“开发设置”-“服务器域名”中进行配置&#xff0c;才能够正常使用。 合法域名的作用&#xff1a; 1.作为小程序请求的 API 服务器域名…

玩转Docker(五):网络

文章目录 〇、关于linux系统网络一、none网络二、host网络三、bridge网络四、user-defined网络 Docker安装时会自动在host上创建三个网络&#xff0c;我们可用docker network ls命令查看&#xff1a; docker network ls那么这几种网络分别有什么含义呢&#xff1f;在回答这个问…

Hive高级语法

-- 通过 hive 加载数据 -- 创建数据表 USE myhivebook; CREATE TABLE IF NOT EXISTS student ( id int, name string ) comment 学生表 row FORMAT delimited fields terminated BY ,; desc formatted student; -- 创建数据 vi /root/data/student.dat 1001,tom 100…

机器视觉技术与应用实战(Chapter Two-03)

2.5 图像滤波和增强 滤波的作用是&#xff1a;图像中包含需要的信息&#xff0c;也包含我们不感兴趣或需要屏蔽的干扰&#xff0c;去掉这些干扰需要使用滤波。 增强的作用是&#xff1a;通过突出或者抑制图像中某些细节&#xff0c;减少图像的噪声&#xff0c;增强图像的视觉效…

Jenkins----基于 CentOS 或 Docker 安装部署Jenkins并完成基础配置

查看原文 文章目录 基于 CentOS7 系统部署 Jenkins 环境基于 Docker 安装部署 Jenkins环境配置 Jenkins 中文模式配置用户名密码形式的 Jenkins 凭据配置 ssh 私钥形式的 Jenkins 凭据配置 Jenkins 执行任务的节点 基于 CentOS7 系统部署 Jenkins 环境 &#xff08;1&#xff…

使用Nginx实现负载均衡的实践指南

目录 前言1 负载均衡简介2 需要实现的效果3 准备2个tomcat服务器4 配置Nginx实现负载均衡5 Nginx的服务器策略5.1 轮询&#xff08;默认&#xff09;5.2 权重&#xff08;weight&#xff09;5.3 IP哈希&#xff08;ip_hash&#xff09;5.4 响应时间公平分配&#xff08;fair&am…

C# DotNetCore AOP简单实现

背景 实际开发中业务和日志尽量不要相互干扰嵌套&#xff0c;否则很难维护和调试。 示例 using System.Reflection;namespace CSharpLearn {internal class Program{static void Main(){int age 25;string name "bingling";Person person new(age, name);Conso…

Day63力扣打卡

打卡记录 寻找最近的回文数&#xff08;模拟&#xff09; 链接 class Solution:def nearestPalindromic(self, n: str) -> str:m len(n)candidates [10 ** (m - 1) - 1, 10 ** m 1]selfPrefix int(n[:(m 1) // 2])for x in range(selfPrefix - 1, selfPrefix 2):y …

[强网杯 2019]Upload

[强网杯 2019]Upload 开放注册直接注册一个账号然后登录进去 先对页面进行简单文件上传测试发现都不存在漏洞对网站进行目录扫描 发现www.tar.gz 打开发现是tp5框架发现源码 这里如果前面信息收集的完整会发现存在反序列化 对注册&#xff0c;登录&#xff0c;上传文件页面分…

React与VUE对照

React 和 Vue.js 都是现代前端开发中非常受欢迎的 JavaScript 框架/库。它们都有各自独特的特点和设计哲学&#xff0c;同时也有一些共同之处。以下是 React 和 Vue.js 的对比&#xff1a; 相似之处&#xff1a; 使用虚拟 DOM&#xff1a;React 和 Vue 都使用虚拟 DOM 来优化…

STM32F103RCT6开发板M3单片机教程06--定时器中断

前言 除非特别说明&#xff0c;本章节描述的模块应用于整个STM32F103xx微控制器系列&#xff0c;因为我们使用是STM32F103RCT6开发板是mini最小系统板。本教程使用是&#xff08;光明谷SUN_STM32mini开发板&#xff09; STM32F10X定时器(Timer)基础 首先了解一下是STM32F10X…

时序预测 | Python实现GRU-XGBoost组合模型电力需求预测

时序预测 | Python实现GRU-XGBoost组合模型电力需求预测 目录 时序预测 | Python实现GRU-XGBoost组合模型电力需求预测预测效果基本描述程序设计参考资料预测效果 基本描述 该数据集因其每小时的用电量数据以及 TSO 对消耗和定价的相应预测而值得注意,从而可以将预期预测与当前…

Linux:超级管理员(root用户)创建用户、用户组

root用户&#xff1a; 拥有最大的系统操作权限,而普通用户在许多地方的权限是受限的。 演示&#xff1a; 1、使用普通用户在根目录下创建文件夹&#xff08;失败&#xff09; 2、切换到root用户后&#xff0c;继续尝试&#xff08;成功&#xff09; 3、普通用户的权限&#…

TCP/IP详解——DNS 流量分析

文章目录 1. DNS 流量分析1.1 DNS 基本概念1.2 DNS 系统特性1.3 DNS 效率问题1.4 域名的组成1.5 域名解析系统1.5.1 域名解析过程 1.6 DNS 记录种类1.7 DNS 的报文格式1.7.1 DNS 报文中的基础结构部分1.7.2 DNS 查询报文中的问题部分1.7.3 DNS 响应报文中的资源记录部分1.7.4 示…

力扣面试150题 | 15.三数之和

力扣面试150题 &#xff5c; 15.三数之和 题目描述解题思路代码实现 题目描述 15.三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回…

【开源项目】WPF 扩展 -- 多画面视频渲染组件

目录 1、项目介绍 2、组件集成 2.1 下载地址 2.2 添加依赖 3、使用示例 3.1 启动动画 3.2 视频渲染 3.3 效果展示 4、项目地址 1、项目介绍 Com.Gitusme.Net.Extensiones.Wpf 是一款 Wpf 扩展组件。基于.Net Core 3.1 开发&#xff0c;当前是第一个发布版本 1.0.0&am…

Java架构师系统架构内部维度分析

目录 1 导语2.1 安全性维度概述2.2 流程安全性2.3 架构安全性2.4 安全维度总结3 伸缩性维度概述和场景思路3.1 无状态应用弹性伸缩3.2 阿里云Knative弹性伸缩3.3 有状态应用弹性伸缩3.4 伸缩性维度总结想学习架构师构建流程请跳转:Java架构师系统架构设计 1 导语

MySQL数据库管理优化及高阶语句(用户,权限,索引,事务,存储引擎,备份,视图,查询,存储过程)

数据库用户管理 新建用户 CREATE USER 用户名来源地址 [IDENTIFIED BY [PASSWORD] 密码]; //用户名&#xff1a;指定将创建的用户名. 来源地址&#xff1a;指定新创建的用户可在哪些主机上登录&#xff0c;可使用IP地址、网段、主机名的形式&#xff0c;本地用户可用localhos…