【Maui】视图界面与数据模型绑定
文章目录
- 前言
- 一、问题描述
- 二、解决方案
- 三、软件开发(源码)
- 3.1 创建模型
- 3.2 视图界面
- 3.3 控制器逻辑层
- 四、项目展示
前言
.NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移动和桌面应用。
使用 .NET MAUI,可从单个共享代码库开发可在 Android、iOS、macOS 和 Windows 上运行的应用。
.NET MAUI 是一款开放源代码应用,是 Xamarin.Forms 的进化版,从移动场景扩展到了桌面场景,并从头重新生成了 UI 控件,以提高性能和可扩展性。 如果以前使用过 Xamarin.Forms 来生成跨平台用户界面,那么你会注意到它与 .NET MAUI 有许多相似之处。 但也有一些差异。 通过使用 .NET MAUI,可使用单个项目创建多平台应用,但如果有必要,可以添加特定于平台的源代码和资源。 .NET MAUI 的主要目的之一是使你能够在单个代码库中实现尽可能多的应用逻辑和 UI 布局。
一、问题描述
MVVM模式(Model-View-ViewModel)架构模式,是将View和ViewModel关联起来,通过双向数据绑定实现View和ViewModel的同步更新。View负责展示数据和用户交互,ViewModel负责处理数据和业务逻辑,Model负责存储数据。MVVM的优点是能够降低View和ViewModel之间的耦合,使得代码更加可维护和可测试。
.NET MAUI是如何进行将View和ViewModel双向绑定的呢?
二、解决方案
1、视图–数据模型绑定:定义ViewModels,视图层通过Binding属性绑定ViewModels;
2、数据模型–视图绑定:ViewModels属性发生改变,需要通知View进行更新,通知采用观察者模式,更新View采用委托Invoke。
听起来很复杂对不对?其实很简单。
三、软件开发(源码)
3.1 创建模型
文件名:TitleBarViewModel.cs
位置:ViewModels
备注:集合一定要定义成 ObservableCollection,不要使用List,否则无法实现MVVM,ObservableCollection实现INotifyCollectionChanged, INotifyPropertyChanged。
using App.Mes.Core.Operation.Services.Mobile;
using Newtonsoft.Json;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace GlueNet.Mobile.ViewModels
{public class TitleBarViewModel : INotifyPropertyChanged{private string _version;private string _workdate;private string _classesValue; //班组private string _userID;private string _userName;private string _userComb; // 用户编号+姓名public ObservableCollection<KeyValuePair<string, string>> ClassesOptions { get; set; } = new ObservableCollection<KeyValuePair<string, string>>();public string ClassesValue{get => _classesValue;set{if (_classesValue != value){_classesValue = value;OnPropertyChanged();}}}public string Version{get => _version;set{_version = value;OnPropertyChanged();}}public string WorkDate{get => _workdate;set{if (_workdate != value){_workdate = value;OnPropertyChanged();}}}public string UserID{get => _userID;set{_userID = value;OnPropertyChanged();}}public string UserName{get => _userName;set{_userName = value;OnPropertyChanged();}}public string UserComb{get => _userComb;set{_userComb = value;OnPropertyChanged();}}/// <summary>/// 构造函数/// </summary>public TitleBarViewModel(){InitializeOptions();}private void InitializeOptions(){//取班组string str_Reason = GycMobileService.Proxy.GetKeyValue("class_group");var ReasonList = JsonConvert.DeserializeObject<List<KeyValuePair<string, string>>>(str_Reason);foreach (var item in ReasonList){ClassesOptions.Add(new KeyValuePair<string, string>(item.Key, item.Value));}ClassesValue = ClassesOptions.FirstOrDefault().Value;}/// <summary>/// 班组/// </summary>public string GetClassesValueByKey(string key){var Classes = ClassesOptions.FirstOrDefault(x => x.Key == key);return Classes.Value;}//实现了INotifyPropertyChanged接口,用于在属性值发生变化时通知界面更新。public event PropertyChangedEventHandler PropertyChanged;//事件委托更新属性protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}
文件名:MO1002DetailsModel.cs
位置:ViewModels
备注:集合一定要定义成 ObservableCollection,不要使用List,否则无法实现MVVM,ObservableCollection实现INotifyCollectionChanged, INotifyPropertyChanged。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace GlueNet.Mobile.Models
{public class MO1002DetailsModel{/// <summary>/// 预留申请单主号/// </summary> public virtual string CReservedNo { get; set; }/// <summary>/// 创建人/// </summary> public virtual string Creator { get; set; }/// <summary>/// 创建人/// </summary> public virtual string CreatorCn { get; set; }/// <summary>/// 创建时间/// </summary> public virtual DateTime? CreateTime { get; set; }/// <summary>/// 创建时间/// </summary> public virtual string CreateTimeText { get; set; }/// <summary>/// 单据类型(1 移库 2 领料 3退库)/// </summary> public virtual string CReservedType { get; set; }/// <summary>/// 单据类型(1 移库 2 领料 3退库)/// </summary> public virtual string CReservedTypeCn { get; set; }/// <summary>/// 物料类型 1-散料 2 纸卷(21大纸,22小纸,23纸垛,26tissue半成品) ( 暂不用mtrl_type)/// </summary> public virtual string CMtrlType { get; set; }/// <summary>/// 物料类型 1-散料 2 纸卷(21大纸,22小纸,23纸垛,26tissue半成品) ( 暂不用mtrl_type)/// </summary> public virtual string CMtrlTypeCn { get; set; }/// <summary>/// 发货实体库代码/// </summary> public virtual string CSendStoreHouse { get; set; }/// <summary>/// 发货实体库代码/// </summary> public virtual string CSendStoreHouseCn { get; set; }/// <summary>/// 发货业务工厂代码/// </summary> public virtual string CSendBnPlantId { get; set; }/// <summary>/// 发货业务工厂/// </summary> public virtual string CSendBnPlantIdCn { get; set; }/// <summary>/// 发货班次/// </summary> public virtual string CClassRate { get; set; }/// <summary>/// 备注/// </summary> public virtual string CRemark { get; set; }/// <summary>/// 备注/// </summary> public virtual string CRemarkCn { get; set; }/// <summary>/// 是否被选中/// </summary> public virtual bool IsCheck { get; set; } = false;}
}
3.2 视图界面
文件名:MO1002Page.xaml
位置:Pages
备注:使用Mode=TwoWay,使用双向绑定,可以不设置观察者模式;
遍历中的RadioButton不要使用CheckedChanged()属性,亲测有bug,在2条数据被删除1条数据时,页面自然只剩1条数据,RadioButton会自动被勾选,但是不会触发CheckedChanged(),不建议使用CheckedChanged()属性。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"x:Class="GlueNet.Mobile.Pages.MO1002Page"Title="件次退料"><StackLayout><!--顶部标题栏--><Grid BackgroundColor="{StaticResource Gray300}" Padding="5"><Grid.RowDefinitions><RowDefinition Height="*" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /></Grid.ColumnDefinitions><!-- 显示当前日期,左边部分 --><DatePicker x:Name="HiddenDatePicker"Date="{Binding TitleBar.WorkDate}"TextColor="White" Format="yyyy-MM-dd"HorizontalOptions="Start" VerticalOptions="Center" Grid.Column="0" DateSelected="OnDateSelected" /><!-- 显示班组,绑定点击事件 --><Label Text="{Binding TitleBar.ClassesValue}"TextColor="White"HorizontalOptions="Center"VerticalOptions="Center"Grid.Column="1"x:Name="ClassesLabel"><Label.GestureRecognizers><TapGestureRecognizer Tapped="OnClassesClicked" /></Label.GestureRecognizers></Label><!-- 显示登录用户名,绑定点击事件 --><Label Text="{Binding TitleBar.UserName}"TextColor="White"HorizontalOptions="Center"VerticalOptions="Center"Grid.Column="2"x:Name="UserNameLabel"></Label></Grid><!--中部数据区域--><ScrollView VerticalOptions="FillAndExpand"><CollectionView ItemsSource="{Binding DataList}" SelectionMode="None"><CollectionView.ItemTemplate><DataTemplate><HorizontalStackLayout><!--必须要,否则前端有bug--><RadioButton GroupName="DataListGroup" IsChecked="{Binding IsCheck, Mode=TwoWay}"/><Frame BorderColor="LightGray" CornerRadius="5" Padding="10" Margin="5"><Grid ColumnDefinitions="*,*,*,*" RowDefinitions="*,*,*,*,*,*"><Label Grid.Column="0" Text="退库单号:" FontSize="Small" /><Label Grid.Column="1" Grid.ColumnSpan="3" Text="{Binding CReservedNo}" FontSize="Small" /><Label Grid.Row="1" Grid.Column="0" Text="单据类型:" FontSize="Small" /><Label Grid.Row="1" Grid.Column="1" Text="{Binding CReservedTypeCn}" FontSize="Small"/><Label Grid.Row="1" Grid.Column="2" Text="物料类型:" FontSize="Small" /><Label Grid.Row="1" Grid.Column="3" Text="{Binding CMtrlTypeCn}" FontSize="Small"/><Label Grid.Row="2" Grid.Column="0" Text="线边库:" FontSize="Small" /><Label Grid.Row="2" Grid.Column="1" Text="{Binding CSendStoreHouseCn}" FontSize="Small"/><Label Grid.Row="3" Grid.Column="0" Text="业务工厂:" FontSize="Small" /><Label Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3" Text="{Binding CSendBnPlantIdCn}" FontSize="Small"/><Label Grid.Row="4" Grid.Column="0" Text="创建人:" FontSize="Small" /><Label Grid.Row="4" Grid.Column="1" Text="{Binding CreatorCn}" FontSize="Small"/><Label Grid.Row="4" Grid.Column="2" Text="创建时间:" FontSize="Small" /><Label Grid.Row="4" Grid.Column="3" Text="{Binding CreateTimeText}" FontSize="Small"/><Label Grid.Row="5" Grid.Column="0" Text="退库原因:" FontSize="Small" /><Label Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="3" Text="{Binding CRemarkCn}" FontSize="Small" /></Grid></Frame></HorizontalStackLayout></DataTemplate></CollectionView.ItemTemplate></CollectionView></ScrollView><!--底部操作栏--><Grid HeightRequest="60" Padding="5" BackgroundColor="{StaticResource Gray300}"><Grid.ColumnDefinitions><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /></Grid.ColumnDefinitions><Button HorizontalOptions="Center" Text="刷新" FontSize="Small" BackgroundColor="LightBlue" Clicked="OnRefreshClicked"/><Button Grid.Column="1" HorizontalOptions="Center" Text="制单" FontSize="Small" BackgroundColor="Green" Clicked="OnAddClicked"/><Button Grid.Column="2" HorizontalOptions="Center" Text="编辑" FontSize="Small" BackgroundColor="YellowGreen" Clicked="OnEditClicked"/><Button Grid.Column="3" HorizontalOptions="Center" Text="删除" FontSize="Small" BackgroundColor="Red" Clicked="OnDeleteClicked"/></Grid></StackLayout></ContentPage>
3.3 控制器逻辑层
定义
private MO1002AllViewModel MO1002List { get; set; } = new MO1002AllViewModel();
界面绑定,也可以在view层绑定
BindingContext = MO1002List;
数据初始化,从服务端取数(可以不看,重点关注数据绑定)
/// <summary>/// 刷新/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private async void OnRefreshClicked(object sender, EventArgs e){try{//按工作日期、制单人查询string str_Result = GycMobileService.Proxy.GetMasterTAX_2010(MO1002List.TitleBar.WorkDate, MO1002List.TitleBar.UserID);var var_MobileResult = JsonConvert.DeserializeObject<MobileResult>(str_Result);string aa = var_MobileResult.RetValue.ToString();if (var_MobileResult.IsSuccess){MO1002List.DataList.Clear();List<Tax2010>? list_Tax2010 = JsonConvert.DeserializeObject<List<Tax2010>>(var_MobileResult.RetValue.ToString());if (list_Tax2010 != null && list_Tax2010.Count > 0){// 创建一个 MO1002AddViewModel 实例来获取线边库的名称var addViewModel = new MO1002AddViewModel();foreach (var item in list_Tax2010){MO1002List.DataList.Add(new MO1002DetailsModel{CReservedNo = item.CReservedNo,Creator = item.Creator,CreatorCn = MO1002List.TitleBar.UserName,//框架未知问题,创建日期数据返回不对CreateTime = item.CreateTime,CreateTimeText = item.CreateTime.ToString("yyyy-MM-dd HH:MM:ss"),//CreateTime = item.LastModifyTime,//CreateTimeText = item.LastModifyTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? string.Empty,CReservedType = item.CReservedType,CReservedTypeCn = "退库",CMtrlType = item.CMtrlType,CMtrlTypeCn = addViewModel.GetMtrlTypeValueByKey(item.CMtrlType),CSendStoreHouse = item.CSendStoreHouse,CSendStoreHouseCn = addViewModel.GetHouseValueByKey(item.CSendStoreHouse),CSendBnPlantId = item.CSendBnPlantId,CSendBnPlantIdCn = addViewModel.GetBnPlantValueByKey(item.CSendBnPlantId),CClassRate = item.CClassRate,CRemark = item.CRemark,CRemarkCn = addViewModel.GetReasonValueByKey(item.CRemark),});}}Toaster.Show(var_MobileResult.Remark);}else{await MessageExtension.Error(var_MobileResult.Remark);}}catch (Exception ex){Toaster.Show(ex.Message);return;}}
获取选中的数据,从集合中取被勾选的数据行。
/// <summary>/// 单选按钮选中事件/// </summary>/// <param name="sender"></param>/// <param "e"></param>private void OnRadioButtonCheckedChanged(){if (MO1002List.DataList != null && MO1002List.DataList.Count > 0){MO1002List.SelectedDetail = MO1002List.DataList.FirstOrDefault(x => x.IsCheck == true) ?? new MO1002DetailsModel();}}
四、项目展示



相关文章:
【Maui】视图界面与数据模型绑定
文章目录 前言一、问题描述二、解决方案三、软件开发(源码)3.1 创建模型3.2 视图界面3.3 控制器逻辑层 四、项目展示 前言 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移动和桌面应用。 使用 .NET MAUI&…...
JavaScript笔记基础篇02——运算符、语句、数组
黑马程序员视频地址:黑马程序员前端JavaScript入门到精通全套视频教程https://www.bilibili.com/video/BV1Y84y1L7Nn?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes 目录 运算符 赋值运算符 编辑编辑 一元运算符…...
心法利器[127] | 24年算法思考-特征工程和经典深度学习
心法利器 本栏目主要和大家一起讨论近期自己学习的心得和体会。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。 2023年新的文章合集已经发布,获取方式看这里:又添十万字-CS的陋室2023年文章合集来袭,更…...
ASP.NET Core 中的 JWT 鉴权实现
在当今的软件开发中,安全性和用户认证是至关重要的方面。JSON Web Token(JWT)作为一种流行的身份验证机制,因其简洁性和无状态特性而被广泛应用于各种应用中,尤其是在 ASP.NET Core 项目里。本文将详细介绍如何在 ASP.…...
PyTorch基本功能与实现代码
PyTorch是一个开源的深度学习框架,提供了丰富的函数和工具,以下为其主要功能的归纳: 核心数据结构: • 张量(Tensor):类似于Numpy的ndarray,是PyTorch中基本的数据结构,…...
SparkSQL数据模型综合实践
文章目录 1. 实战概述2. 实战步骤2.1 创建数据集2.2 创建数据模型对象2.2.1 创建常量2.2.2 创建加载数据方法2.2.3 创建过滤年龄方法2.2.4 创建平均薪水方法2.2.5 创建主方法2.2.6 查看完整代码 2.3 运行程序,查看结果 3. 实战小结 1. 实战概述 在本次实战中&#…...
3 查找重复的电子邮箱(having与where区别,distinct去重使用)
3 查找重复的电子邮箱(having与where区别,distinct去重使用) 表: Person ---------------------- | Column Name | Type | ---------------------- | id | int | | email | varchar | ---------------------- id 是该…...
uniapp——App 监听下载文件状态,打开文件(三)
5 实现下载文件并打开 这里演示,导出Excel 表格 文章目录 5 实现下载文件并打开DEMO监听下载进度效果图为什么 totalSize 一直为0? 相关Api: downloader DEMO 提示: 请求方式支持:GET、POST;POST 方式需要…...
循环队列(C语言)
从今天开始我会开启一个专栏leetcode每日一题,大家互相交流代码经验,也当作我每天练习的自我回顾。第一天的内容是leetcode622.设计循环队列。 一、题目详细 设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO&#…...
数据可视化:让数据讲故事的艺术
目录 1 前言2 数据可视化的基本概念2.1 可视化的核心目标2.2 传统可视化手段 3 数据可视化在知识图谱中的应用3.1 知识图谱的可视化需求3.2 知识图谱的可视化方法 4 数据可视化叙事:让数据讲故事4.1 叙事可视化的关键要素4.2 数据可视化叙事的实现方法 5 数据可视化…...
雷电9最新版安装Magisk+LSPosd(新手速通)
大家好啊!我是NiJiMingCheng 我的博客:NiJiMingCheng 在安卓系统的定制与拓展过程中,获取 ROOT 权限以及安装各类框架是进阶玩家常用的操作,这可以帮助我们实现更多系统层面的个性化功能。今天,我将为大家详细介绍如何…...
Ubuntu 24.04 LTS 开启 SMB 服务,并通过 windows 访问
Ubuntu 24.04 LTS 背景资料 Ubuntu服务器折腾集Ubuntu linux 文件权限Ubuntu 空闲硬盘挂载到 文件管理器的 other locations Ubuntu开启samba和window共享文件 Ubuntu 配置 SMB 服务 安装 Samba 确保 Samba 已安装。如果未安装,运行以下命令进行安装ÿ…...
使用Websocket进行前后端实时通信
1、引入jar,spring-websocket-starter <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency> 2、配置websocket config import org.springframe…...
vue2使用flv.js在浏览器打开flv格式视频
组件地址:GitHub - bilibili/flv.js: HTML5 FLV Player flv.js 仅支持 H.264 和 AAC/MP3 编码的 FLV 文件。如果视频文件使用了其他编码格式就打不开。 flv.vue <template><div><el-dialog :visible.sync"innerVisibleFlv" :close-on-pre…...
OpenCV相机标定与3D重建(61)处理未校准的立体图像对函数stereoRectifyUncalibrated()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 为未校准的立体相机计算一个校正变换。 cv::stereoRectifyUncalibrated 是 OpenCV 库中的一个函数,用于处理未校准的立体图像对。该函…...
[cg] glProgramBinary
参考: glProgramBinary - OpenGL 4 Reference Pages opengl 通过gpu编译好的 shader 可以存储到二进制文件中,第二次使用的时候直接加载二进制文件即可, glProgramBinary用于加载shader的二进制数据 实列代码如下: // 假设已经…...
LeetCode hot 力扣热题100 二叉树的最大深度
class Solution { public:int maxDepth(TreeNode* root) {if (root nullptr) {return 0;}int l_depth maxDepth(root->left);int r_depth maxDepth(root->right);return max(l_depth, r_depth) 1;} }; 代码作用 该函数通过递归计算二叉树的最大深度(从根节…...
速通Docker === 网络
目录 Docker网络详解 容器之间直接通信的弊端 (一)启动容器 (二)进入容器并发起请求 (三)请求流程 (四) 弊端分析 一、Docker网络基础 (一)容器IP分配…...
【MySQL — 数据库基础】深入解析MySQL常用数据类型
常用数据类型 创建完数据库之后,就要在数据库中创建表,表中存储的数据记录,一条记录由不同的列组成,每条列都需要自己的类型;并且表中的多个行对应的列的数据类型,都必须是相同的; 那么每个…...
Linux高级--3.3.1 C++ spdlog 开源异步日志方案
一、基本介绍 spdlog 是由 Gustav S. 在 2015 年开发的一个高性能 C 日志库。开发这个库的主要目的是为了提供一个非常快速、轻量、易于使用的日志工具,特别适合需要高性能、低延迟日志记录的 C 应用程序。(由于源码现在比较难下载,我把压缩…...
OpenClaw用户如何快速接入Taotoken并开始Agent工作流
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 OpenClaw用户如何快速接入Taotoken并开始Agent工作流 对于使用OpenClaw框架构建AI智能体的开发者而言,快速接入稳定、多…...
为什么软件开发偏爱 Linux?深度剖析 Linux 相较于 Windows 的核心优势
引言 在软件开发的世界里,一个有趣的现象是:无论是大型互联网公司的服务器集群,还是资深程序员的个人开发机,Linux 操作系统的身影无处不在。与之形成鲜明对比的是,尽管 Windows 在个人消费市场占据绝对主导地位&…...
2026年一键生成论文工具对比实测:5款神器从选题到格式全流程护航
写论文的焦虑,是每个科研人和学生都心照不宣的“隐形压力”。选题无从下手,文献检索耗时费力,逻辑框架反复推翻,格式排版让人抓狂,查重降重更是像在和系统玩“猫鼠游戏”。2026年的AI工具早已不是过去那种“打字机”&a…...
Burp Suite拦截与替换机制深度解析:从协议层到规则链
1. 这不是“点开就能用”的功能,而是你和目标系统之间的一道可编程闸门很多人第一次在Burp Suite里点开Proxy → Intercept,看到HTTP请求被拦下来,兴奋地改个User-Agent、删个Cookie就点Forward,以为自己已经掌握了“拦截与替换”…...
Ubuntu经常安装软件
1、垃圾清理工具stacer sudo apt updatesudo apt install stacer apt cleanapt autocleanapt autoremove 2、类似与everything的工具Fsearcch 1sudo add-apt-repository ppa:christian-boxdoerfer/fsearch-stable 2sudo apt update 3sudo apt install fsearch (注…...
用PyTorch复现FactorVAE:一个能同时预测收益和风险的量化模型实战教程
用PyTorch实战FactorVAE:构建收益与风险双预测的量化模型 在量化投资领域,传统线性因子模型正逐渐被非线性机器学习方法所取代。然而金融数据特有的低信噪比特性,使得直接从市场数据中提取有效因子成为一项艰巨挑战。本文将深入探讨如何利用P…...
PostgreSQL Join 执行策略(Nested Loop、Hash Join、Merge Join)与 NOT EXISTS 优化
以集成数据压缩 SQL 优化为例,用大白话讲清楚 Nested Loop、Hash Join、Merge Join 三种执行策略。一、背景:一条慢 SQL 引发的思考 在对上游下发数据做压缩时,有这样一条 UPDATE SQL: -- ❌ 原始写法 UPDATE magellan_nk_order_i…...
【独家首发】Sora 2 AVI支持并非“开箱即用”:3层封装校验机制详解(RIFF→AVI→OpenCV Mat内存映射链路图解)
更多请点击: https://codechina.net 第一章:Sora 2 AVI支持并非“开箱即用”:核心矛盾与技术定位 Sora 2 的官方文档与发布说明中明确将 AVI 视为“实验性容器支持”,而非默认启用的输入格式。其底层解码栈基于 FFmpeg 5.1 构建&…...
面试官问LinkedBlockingQueue和ArrayBlockingQueue区别?别只答有界无界了,这3个实战坑才是重点
面试官追问LinkedBlockingQueue与ArrayBlockingQueue?别只答基础区别,这3个实战陷阱才是关键 当面试官抛出"LinkedBlockingQueue和ArrayBlockingQueue有什么区别"这个问题时,80%的候选人会条件反射般回答"一个有界一个无界&qu…...
线程池面试
线程池面试|一页极简口述满分版(高级开发必背) 一、核心概念解析(口述满分) 线程池核心作用:实现线程复用,规避线程频繁创建、销毁的性能开销,同时实现并发限流、服务熔断防护、异步…...
