flutter3_douyin:基于flutter3+dart3短视频直播实例|Flutter3.x仿抖音
flutter3-dylive 跨平台仿抖音短视频直播app实战项目。
全新原创基于
flutter3.19.2+dart3.3.0+getx
等技术开发仿抖音app实战项目。实现了类似抖音整屏丝滑式上下滑动视频、左右滑动切换页面模块,直播间进场/礼物动效,聊天等模块。
运用技术
- 编辑器:vscode
- 技术框架:flutter3.19.2+dart3.3.0
- 路由/状态插件:get: ^4.6.6
- 缓存服务:get_storage: ^2.1.1
- 图片预览插件:photo_view: ^0.14.0
- 刷新加载:easy_refresh^3.3.4
- toast轻提示:toast^0.3.0
- 视频套件:media_kit: ^1.1.10+1
Flutter-dyLive实现了类似抖音全屏上下滑动、左右切换页面效果。
左右滑动的同时,顶部状态栏+Tab菜单+底部bottomNavigationBar导航栏三者联动效果。
目录结构
本篇分享主要是短视频和直播模块,至于其它技术知识点,大家可以去看看之前分享的flutter3聊天实例文章。
https://blog.csdn.net/yanxinyun1990/article/details/136051099
https://blog.csdn.net/yanxinyun1990/article/details/136410049
flutter底部导航菜单
使用 bottomNavigationBar
组件实现底部导航页面模块切换。通过getx
状态来联动控制底部导航栏背景颜色。
中间图标/图片按钮,使用了 Positioned
组件定位实现功能。
return Scaffold(backgroundColor: Colors.grey[50],body: pageList[pageCurrent],// 底部导航栏bottomNavigationBar: Theme(// Flutter去掉BottomNavigationBar底部导航栏的水波纹data: ThemeData(splashColor: Colors.transparent,highlightColor: Colors.transparent,hoverColor: Colors.transparent,),child: Obx(() {return Stack(children: [Container(decoration: const BoxDecoration(border: Border(top: BorderSide(color: Colors.black54, width: .1)),),child: BottomNavigationBar(backgroundColor: bottomNavigationBgcolor(),fixedColor: FStyle.primaryColor,unselectedItemColor: bottomNavigationItemcolor(),type: BottomNavigationBarType.fixed,elevation: 1.0,unselectedFontSize: 12.0,selectedFontSize: 12.0,currentIndex: pageCurrent,items: [...pageItems],onTap: (index) {setState(() {pageCurrent = index;});},),),// 自定义底部导航栏中间按钮Positioned(left: MediaQuery.of(context).size.width / 2 - 15,top: 0,bottom: 0,child: InkWell(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// Icon(Icons.tiktok, color: bottomNavigationItemcolor(centerDocked: true), size: 32.0,),Image.asset('assets/images/applogo.png', width: 32.0, fit: BoxFit.contain,)// Text('直播', style: TextStyle(color: bottomNavigationItemcolor(centerDocked: true), fontSize: 12.0),)],),onTap: () {setState(() {pageCurrent = 2;});},),),],);}),),
);
import 'package:flutter/material.dart';
import 'package:get/get.dart';import '../styles/index.dart';
import '../../controllers/page_video_controller.dart';// 引入pages页面
import '../pages/index/index.dart';
import '../pages/video/index.dart';
import '../pages/live/index.dart';
import '../pages/message/index.dart';
import '../pages/my/index.dart';class Layout extends StatefulWidget {const Layout({super.key});State<Layout> createState() => _LayoutState();
}class _LayoutState extends State<Layout> {PageVideoController pageVideoController = Get.put(PageVideoController());// page索引int pageCurrent = 0;// page页面List pageList = [const Index(), const FVideo(), const FLiveList(), const Message(), const My()];// tabs选项List pageItems = [const BottomNavigationBarItem(icon: Icon(Icons.home_outlined),label: '首页'),const BottomNavigationBarItem(icon: Icon(Icons.play_arrow_outlined),label: '短视频'),const BottomNavigationBarItem(icon: Icon(Icons.live_tv_rounded, color: Colors.transparent,),label: ''),BottomNavigationBarItem(icon: Stack(alignment: const Alignment(4, -2),children: [const Icon(Icons.messenger_outline),FStyle.badge(1)],),label: '消息'),BottomNavigationBarItem(icon: Stack(alignment: const Alignment(1.5, -1),children: [const Icon(Icons.person_outline),FStyle.badge(0, isdot: true)],),label: '我')];// 底部导航栏背景色Color bottomNavigationBgcolor() {int index = pageCurrent;int pageVideoTabIndex = pageVideoController.pageVideoTabIndex.value;Color color = Colors.white;if(index == 1) {if([1, 2, 3].contains(pageVideoTabIndex)) {color = Colors.white;}else {color = Colors.black;}}return color;}// 底部导航栏颜色Color bottomNavigationItemcolor({centerDocked = false}) {int index = pageCurrent;int pageVideoTabIndex = pageVideoController.pageVideoTabIndex.value;Color color = Colors.black54;if(index == 1) {if([1, 2, 3].contains(pageVideoTabIndex)) {color = Colors.black54;}else {color = Colors.white60;}}else if(index == 2 && centerDocked) {color = FStyle.primaryColor;}return color;}// ...
}
flutter3实现抖音沉浸式滑动
使用TabBar
组件和PageView
组件实现顶部菜单和页面联动切换效果。
return Scaffold(extendBodyBehindAppBar: true,appBar: AppBar(forceMaterialTransparency: true,backgroundColor: [1, 2, 3].contains(pageVideoController.pageVideoTabIndex.value) ? null : Colors.transparent,foregroundColor: [1, 2, 3].contains(pageVideoController.pageVideoTabIndex.value) ? Colors.black : Colors.white,titleSpacing: 1.0,leading: Obx(() => IconButton(icon: Icon(Icons.menu, color: tabColor(),), onPressed: () {},),),title: Obx(() {return TabBar(controller: tabController,tabs: pageTabs.map((v) => Tab(text: v)).toList(),isScrollable: true,tabAlignment: TabAlignment.center,overlayColor: MaterialStateProperty.all(Colors.transparent),unselectedLabelColor: unselectedTabColor(),labelColor: tabColor(),indicatorColor: tabColor(),indicatorSize: TabBarIndicatorSize.label,unselectedLabelStyle: const TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei'),labelStyle: const TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei', fontWeight: FontWeight.w600),dividerHeight: 0,labelPadding: const EdgeInsets.symmetric(horizontal: 10.0),indicatorPadding: const EdgeInsets.symmetric(horizontal: 5.0),onTap: (index) {pageVideoController.updatePageVideoTabIndex(index); // 更新索引pageController.jumpToPage(index);},);}),actions: [Obx(() => IconButton(icon: Icon(Icons.search, color: tabColor(),), onPressed: () {},),),],),body: Column(children: [Expanded(child: Stack(children: [/// 水平滚动模块PageView(// 自定义滚动行为(支持桌面端滑动、去掉滚动条槽)scrollBehavior: PageScrollBehavior().copyWith(scrollbars: false),scrollDirection: Axis.horizontal,controller: pageController,onPageChanged: (index) {pageVideoController.updatePageVideoTabIndex(index); // 更新索引setState(() {tabController.animateTo(index);});},children: [...pageModules],),],),),],),
);
PageVideoController pageVideoController = Get.put(PageVideoController());List<String> pageTabs = ['热点', '长视频', '文旅', '商城', '关注', '同城服务', '推荐'];
final pageModules = [const HotModule(),const LongVideoModule(),const TripModule(),const MallModule(),const FavorModule(),const NearModule(),const RecommendModule()
];
late final TabController tabController = TabController(initialIndex: pageVideoController.pageVideoTabIndex.value, length: pageTabs.length, vsync: this);
// 页面controller
late final PageController pageController = PageController(initialPage: pageVideoController.pageVideoTabIndex.value, viewportFraction: 1.0);
void dispose() {tabController.dispose();pageController.dispose();super.dispose();
}
flutter实现短视频底部播放拖拽条
短视频底部又一条mini播放进度条,可实时显示视频播放进度,可拖拽到指定播放时间点。
// flutter滑动短视频模块 Q:282310962return Container(color: Colors.black,child: Column(children: [Expanded(child: Stack(children: [/// 垂直滚动模块PageView.builder(// 自定义滚动行为(支持桌面端滑动、去掉滚动条槽)scrollBehavior: PageScrollBehavior().copyWith(scrollbars: false),scrollDirection: Axis.vertical,controller: pageController,onPageChanged: (index) async {...},itemCount: videoList.length,itemBuilder: (context, index) {return Stack(children: [// 视频区域Positioned(top: 0,left: 0,right: 0,bottom: 0,child: GestureDetector(child: Stack(children: [// 短视频插件Visibility(visible: videoIndex == index,child: Video(controller: videoController,fit: BoxFit.cover,// 无控制条controls: NoVideoControls,),),// 播放/暂停按钮StreamBuilder(stream: player.stream.playing,builder: (context, playing) {return Visibility(visible: playing.data == false,child: Center(child: IconButton(padding: EdgeInsets.zero,onPressed: () {player.playOrPause();},icon: Icon(playing.data == true ? Icons.pause : Icons.play_arrow_rounded,color: Colors.white70,size: 70,),),),);},),],),onTap: () {player.playOrPause();},),),// 右侧操作栏Positioned(bottom: 15.0,right: 10.0,child: Column(...),),// 底部信息区域Positioned(bottom: 15.0,left: 10.0,right: 80.0,child: Column(...),),// 播放mini进度条Positioned(bottom: 0.0,left: 10.0,right: 10.0,child: Visibility(visible: videoIndex == index && position > Duration.zero,child: Listener(child: SliderTheme(data: const SliderThemeData(trackHeight: 2.0,thumbShape: RoundSliderThumbShape(enabledThumbRadius: 4.0), // 调整滑块的大小// trackShape: RectangularSliderTrackShape(), // 使用矩形轨道形状overlayShape: RoundSliderOverlayShape(overlayRadius: 0), // 去掉Slider默认上下边距间隙inactiveTrackColor: Colors.white24, // 设置非活动进度条的颜色activeTrackColor: Colors.white, // 设置活动进度条的颜色thumbColor: Colors.pinkAccent, // 设置滑块的颜色overlayColor: Colors.transparent, // 设置滑块覆盖层的颜色),child: Slider(value: sliderValue,onChanged: (value) async {// debugPrint('当前视频播放时间$value');setState(() {sliderValue = value;});// 跳转播放时间await player.seek(duration * value.clamp(0.0, 1.0));},onChangeEnd: (value) async {setState(() {sliderDraging = false;});// 继续播放if(!player.state.playing) {await player.play();}},),),onPointerMove: (e) {setState(() {sliderDraging = true;});},),),),// 视频播放时间Positioned(bottom: 90.0,left: 10.0,right: 10.0,child: Visibility(visible: sliderDraging,child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [Text(position.label(reference: duration), style: const TextStyle(color: Colors.white, fontSize: 16.0, fontWeight: FontWeight.w600),),Container(margin: const EdgeInsets.symmetric(horizontal: 7.0),child: const Text('/', style: TextStyle(color: Colors.white54, fontSize: 10.0,),),),Text(duration.label(reference: duration), style: const TextStyle(color: Colors.white54, fontSize: 16.0, fontWeight: FontWeight.w600),),],),),),],);},),/// 固定层// 红包Positioned(left: 15.0,top: MediaQuery.of(context).padding.top + 20,child: Container(height: 40.0,width: 40.0,decoration: BoxDecoration(color: Colors.black12,borderRadius: BorderRadius.circular(100.0),),child: UnconstrainedBox(child: Image.asset('assets/images/time-hb.png', width: 30.0, fit: BoxFit.contain,),),),),],),),],),
);
flutter3直播模块
// 商品购买动效
Container(...
),// 加入直播间动效
const AnimationLiveJoin(joinQueryList: [{'avatar': 'assets/images/logo.png', 'name': 'andy'},{'avatar': 'assets/images/logo.png', 'name': 'jack'},{'avatar': 'assets/images/logo.png', 'name': '一条咸鱼'},{'avatar': 'assets/images/logo.png', 'name': '四季平安'},{'avatar': 'assets/images/logo.png', 'name': '叶子'},],
),// 送礼物动效
const AnimationLiveGift(giftQueryList: [{'label': '小心心', 'gift': 'assets/images/gift/gift1.png', 'user': 'Jack', 'avatar': 'assets/images/avatar/uimg2.jpg', 'num': 12},{'label': '棒棒糖', 'gift': 'assets/images/gift/gift2.png', 'user': 'Andy', 'avatar': 'assets/images/avatar/uimg6.jpg', 'num': 36},{'label': '大啤酒', 'gift': 'assets/images/gift/gift3.png', 'user': '一条咸鱼', 'avatar': 'assets/images/avatar/uimg1.jpg', 'num': 162},{'label': '人气票', 'gift': 'assets/images/gift/gift4.png', 'user': 'Flower', 'avatar': 'assets/images/avatar/uimg5.jpg', 'num': 57},{'label': '鲜花', 'gift': 'assets/images/gift/gift5.png', 'user': '四季平安', 'avatar': 'assets/images/avatar/uimg3.jpg', 'num': 6},{'label': '捏捏小脸', 'gift': 'assets/images/gift/gift6.png', 'user': 'Alice', 'avatar': 'assets/images/avatar/uimg4.jpg', 'num': 28},{'label': '你真好看', 'gift': 'assets/images/gift/gift7.png', 'user': '叶子', 'avatar': 'assets/images/avatar/uimg7.jpg', 'num': 95},{'label': '亲吻', 'gift': 'assets/images/gift/gift8.png', 'user': 'YOYO', 'avatar': 'assets/images/avatar/uimg8.jpg', 'num': 11},{'label': '玫瑰', 'gift': 'assets/images/gift/gift12.png', 'user': '宇辉', 'avatar': 'assets/images/avatar/uimg9.jpg', 'num': 3},{'label': '私人飞机', 'gift': 'assets/images/gift/gift16.png', 'user': 'Hison', 'avatar': 'assets/images/avatar/uimg10.jpg', 'num': 273},],
),// 直播弹幕+商品讲解
Container(margin: const EdgeInsets.only(top: 7.0),height: 200.0,child: Row(crossAxisAlignment: CrossAxisAlignment.end,children: [Expanded(child: ListView.builder(padding: EdgeInsets.zero,itemCount: liveJson[index]['message']?.length,itemBuilder: (context, i) => danmuList(liveJson[index]['message'])[i],),),SizedBox(width: isVisibleGoodsTalk ? 7 : 35,),// 商品讲解Visibility(visible: isVisibleGoodsTalk,child: Column(...),),],),
),// 底部工具栏
Container(margin: const EdgeInsets.only(top: 7.0),child: Row(...),
),
直播间从右到左进入直播间动画及礼物左侧滑入效果,通过 SlideTransition 组件实现进场动画。
return SlideTransition(position: animationFirst ? animation : animationMix,child: Container(alignment: Alignment.centerLeft,margin: const EdgeInsets.only(top: 7.0),padding: const EdgeInsets.symmetric(horizontal: 7.0,),height: 23.0,width: 250,decoration: const BoxDecoration(gradient: LinearGradient(begin: Alignment.centerLeft,end: Alignment.centerRight,colors: [Color(0xFF6301FF), Colors.transparent],),borderRadius: BorderRadius.horizontal(left: Radius.circular(10.0)),),child: joinList!.isNotEmpty ? Text('欢迎 ${joinList![0]['name']} 加入直播间', style: const TextStyle(color: Colors.white, fontSize: 14.0,),):Container(),),
);
class _AnimationLiveJoinState extends State<AnimationLiveJoin> with TickerProviderStateMixin {// 动画控制器late AnimationController controller = AnimationController(vsync: this,duration: const Duration(milliseconds: 500), // 第一个动画持续时间);late AnimationController controllerMix = AnimationController(vsync: this,duration: const Duration(milliseconds: 1000), // 第二个动画持续时间);// 动画late Animation<Offset> animation = Tween(begin: const Offset(2.5, 0), end: const Offset(0, 0)).animate(controller);late Animation<Offset> animationMix = Tween(begin: const Offset(0, 0), end: const Offset(-2.5, 0)).animate(controllerMix);Timer? timer;// 是否第一个动画bool animationFirst = true;// 是否空闲bool idle = true;// 加入直播间数据列表List? joinList;void initState() {super.initState();joinList = widget.joinQueryList!.toList();runAnimation();animation.addListener(() {if(animation.status == AnimationStatus.forward) {debugPrint('第一个动画进行中');idle = false;setState(() {});}else if(animation.status == AnimationStatus.completed) {debugPrint('第一个动画结束');animationFirst = false;if(controllerMix.isCompleted || controllerMix.isDismissed) {timer = Timer(const Duration(seconds: 2), () {controllerMix.forward();debugPrint('第二个动画开始');});}setState(() {});}});animationMix.addListener(() {if(animationMix.status == AnimationStatus.forward) {setState(() {});}else if(animationMix.status == AnimationStatus.completed) {animationFirst = true;controller.reset();controllerMix.reset();if(joinList!.isNotEmpty) {joinList!.removeAt(0);}idle = true;// 执行下一个数据runAnimation();setState(() {});}});}void runAnimation() {if(joinList!.isNotEmpty) {// 空闲状态才能执行,防止添加数据播放状态混淆if(idle == true) {if(controller.isCompleted || controller.isDismissed) {setState(() {});timer = Timer(Duration.zero, () {controller.forward();});}}}}void dispose() {controller.dispose();controllerMix.dispose();timer?.cancel();super.dispose();}}
另外项目中还加入了之前flutter3聊天功能模块。
Ok,综上就是flutter3+dart3仿抖音app实例的一些技术知识分享,希望对大家有所帮助。
最后附上两个实例项目
-
uni-app+vue3+vk-uview多端直播商城项目
https://blog.csdn.net/yanxinyun1990/article/details/135329724 -
vue3+vite4中后台管理系统
https://blog.csdn.net/yanxinyun1990/article/details/130144212
相关文章:

flutter3_douyin:基于flutter3+dart3短视频直播实例|Flutter3.x仿抖音
flutter3-dylive 跨平台仿抖音短视频直播app实战项目。 全新原创基于flutter3.19.2dart3.3.0getx等技术开发仿抖音app实战项目。实现了类似抖音整屏丝滑式上下滑动视频、左右滑动切换页面模块,直播间进场/礼物动效,聊天等模块。 运用技术 编辑器&#x…...

VR全景赋能智慧农业,打造沉浸式种植体验平台
随着人口的增长,传统农业也正在面临着不一样的挑战,加上很多人对农业的固有印象,很少有年轻人愿意下到农田里,那么该如何提高产量、降低成本以及引导年轻人深刻感受现代农业成为了急需解决的问题。 随着城市化脚步的推进ÿ…...

百度文心一言(ERNIE bot)API接入Android应用
百度文心一言(ERNIE bot)API接入Android应用实践 - 拾一贰叁 - 博客园 (cnblogs.com) Preface: 现在生成式AI越来越强大了,想在android上实现一个对话助手的功能,大概摸索了一下接入百度文心一言API的方法。 与AI助手交换信息的…...
springboot基本使用八(mbatisplus+filter实现登录功能)
mybatisplus依赖: <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version> </dependency> mysql依赖: <dependency><groupId>com.mysql<…...

蚂蚁庄园今天答案
蚂蚁庄园是一款爱心公益游戏,用户可以通过喂养小鸡,产生鸡蛋,并通过捐赠鸡蛋参与公益项目。用户每日完成答题就可以领取鸡饲料,使用鸡饲料喂鸡之后,会可以获得鸡蛋,可以通过鸡蛋来进行爱心捐赠。其中&#…...

第5章 数据建模和设计
思维导图 5.1 引言 最常见的6种模式:关系模式、多维模式、面向对象模式、 事实模式、时间序列模式和NoSQL模式 每种模式分为三层模型:概念模型、逻辑模型和物理模型 每种模型都包含一系列组件:如实体、关系、事实、键和属性。 5.1.1 业务驱…...

牛客NC108 最大正方形【中等 动态规划 Java,Go,PHP】
题目 题目链接: https://www.nowcoder.com/practice/0058c4092cec44c2975e38223f10470e 思路 动态规划: 先初始化第一行和第一列。然后其他单元格依赖自己的上边,左边和左上角参考答案Java import java.util.*;public class Solution {/*** 代码中的类…...

C#学生信息成绩管理系统
一、系统功能描述 本系统包括两类用户:学生、管理员。管理员可以通过系统来添加管理员信息、修改管理员信息、添加学生信息、修改学生信息;开设课程、查询课程、录入成绩、统计成绩、修改成绩、修改个人密码等,而学生则可以通过系统来选择课…...

精品凉拌菜系列热卤系列课程
这一系列课程涵盖精美凉拌菜和美味热卤菜的制作技巧。学员将学习如何选材、调味和烹饪,打造口感丰富、色香俱佳的菜肴。通过实践训练,掌握独特的烹饪技能,为家庭聚餐或职业厨艺提升增添亮点。 课程大小:6.6G 课程下载࿱…...

Java代码基础算法练习-求一个三位数的各位数字之和-2024.03.27
任务描述: 输入一个正整数n(取值范围:100<n<1000),然后输出每位数字之和 任务要求: 代码示例: package M0317_0331;import java.util.Scanner;public class m240327 {public static voi…...

Excel 十字交叉聚光灯查询,再也不用担心看串行与列
当Excel表格行列较多时,要想跟条件找到目标数据可以用查找引用函数自动调取,如果又想让找出来的结果突出显示,有什么好办法呢? 先来看一个做好的案例效果,用户选择查询条件后,结果突出显示。 当查询条件变…...
集合和字符串的使用
文章目录 一、集合概述二、Collection2.1 List接口2.2 Set接口(不常用)2.2.1 TreeSet 三、Map接口四、Collections工具类五、String六、String类型转换6.1 基本数据类型6.2 基本数据类型、包装类 --> String6.3 String与char[]6.4 String与byte[] 一、…...

Wagtail-基于Python Django的内容管理系统CMS实现公网访问
目录 ⛳️推荐 前言 1. 安装并运行Wagtail 1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具 3. 实现Wagtail公网访问 4. 固定Wagtail公网地址 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给…...
Python入门级题目及答案
前言: 学习Python作为一门编程语言是非常有必要的,因为Python简单易学,功能强大,应用广泛。在本篇博客中,我们将提供八道Python入门级的题目,每道题目都伴有详细的描述和对应的答案代码。通过完成这八道题目…...

【C语言基础】:字符串函数(二)
文章目录 一、strncpy函数的使用二、strncat函数的使用三、strncmp函数的使用四、strstr函数的使用和模拟实现4.1 strstr函数的使用4.2 strstr函数的模拟实现 五、strtok函数的使用六、strerror函数的使用 书山有路勤为径,学海无涯苦作舟。 创作不易,宝子…...
【Docker】Docker资源(创建容器)CPU/内存/磁盘IO/GPU限制与分配教程
Docker资源创建容器CPU/内存/磁盘IO/GPU限制与分配 一、关键概念解释二、Docker分配CPU资源限制三、Docker分配内存资源限制四、Docker容器中对磁盘IO进行限制五、Docker对GPU资源限制管理 一、关键概念解释 【cgroup】 cgroups名称源自控制组群(control g…...

发展规划--IM系统
1、时代背景 5G应用,多终端应用,物联网应用,小程序,工业互联,大数据应用等等大前端时代的到来,程序员不能只关注crud,因为以后的服务并发量只会越来越多。 高并发架构师、大数据架构师或者说j…...

stm32平衡车
目录 一.所需材料 二.PID算法(简单说明) 直立环 速度环 串级PID 三.使用到的外设 1.定时器输出比较-PWM 2.定时器编码器模式 3.编码器读取速度 4.电机驱动函数 5.外部中断 四、小车 调试 一.所需材料 1.陀螺仪MPU6050--读取三轴的加速度…...
google浏览器下载文件提示无法安全地下载怎么解决?
在使用google浏览器下载文件的时候,弹出了“无法安全下载”的提示,搞了文件都下载不下来,网上查了一下,是因为chrome认为使用非https链接下载文件是不安全的,在新版本中阻止了用户下载。 目录 1、打开google浏览器的设置...

Navicat 干货 | 通过检查约束确保 PostgreSQL 的数据完整性
数据完整性对于任何数据库系统来说都是很重要的一方面,它确保存储的数据保持准确、一致且有意义的。在 PostgreSQL 中,维护数据完整性的一个强大工具是使用检查约束。这些约束允许你定义数据必须遵守的规则,以防止无效数据的插入或修改。本文…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...

DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...