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

Flutter中的异步编程

目录

前言

1. Future 和 async/await

1.Future

1.什么是Future?

2.Flutter的三种状态

1.未完成(Uncompleted) 

1.定义      

2.处理未完成的Future

2.已完成(Completed with a value)

1.概念

2.处理已完成的Future

3.使用async/await

4.Future的已完成状态的处理

3.已失败(Completed with an error)

1.概念

2.处理失败状态的Future

3.使用 async/await

4.捕获和处理错误的最佳实践

1.始终捕获错误

2.提供用户反馈

3.记录错误

3.创建Future

1.使用Future构造函数

2.使用Future.delayed

3.使用Future.value和Future.error

4.处理Future

1.使用then和catchError

2.使用async/await

3.Future的链式调用

2. Stream

1.Stream的两种类型

2.创建Stream

1.使用StreamController

2.使用异步生成器函数

3.监听Stream

4.使用StreamBuilder

5.Stream的高级用法

1.转换Stream

2.合并Stream

6.总结

3.FutureBuilder和StreamBuilder

1.FutureBuilder

2.StreamBuilder


前言

        在Flutter应用程序开发中,异步编程是必不可少的。异步编程使应用程序能够在不阻塞主线程的情况下执行耗时操作,如网络请求、文件读取和数据库访问。本文将介绍Flutter中常用的异步编程方法及其最佳实践。

1. Future 和 async/await

1.Future

1.什么是Future?

        在Flutter中,Future是一个用于表示异步操作结果的类。它代表一个在将来某个时刻会完成的计算,类似于其他编程语言中的Promise。Future非常适合处理那些需要一些时间才能完成的操作,例如网络请求、文件读取或其他耗时任务。

2.Flutter的三种状态

1.未完成(Uncompleted) 
1.定义      

        表示异步操作尚未完成。在未完成状态的时候,Future尚未提供结果,也没有抛出错误。

        当你调用一个异步函数时,它会返回一个未完成的 Future。该 Future 正在等待函数的异步操作完成或抛出错误。

        以下是一个创建和使用Future的示例,展示Future在未完成状态时的行为:

Future<String> fetchData() {// 创建一个延迟两秒后完成的Futurereturn Future.delayed(Duration(seconds: 2), () => 'Data fetched');
}void main() {print('Fetching data...');fetchData().then((result) {print(result);}).catchError((error) {print('Error: $error');});print('Waiting for data...');
}

        控制台输入信息如下:

Fetching data...
Waiting for data...
Data fetched

        这里可以看到,在调用fetchData之后和Future完成之前,控制台输出了”Waiting for data…”。这表示在这段时间内,Future处于未完成状态。

2.处理未完成的Future

        通常,我们使用then方法来处理Future完成时的结果,使用catchError方法来处理Future失败时的错误。

        此外,可以使用await关键字在异步函数中等待Future完成:

Future<void> fetchDataAndPrint() async {print('Fetching data...');try {String result = await fetchData();print(result);} catch (error) {print('Error: $error');}print('Data fetching completed.');
}void main() {fetchDataAndPrint();
}

        执行这个代码时,控制台的输出如下:

Fetching data...
Data fetched
Data fetching completed.

2.已完成(Completed with a value)
1.概念

        已完成状态表示异步操作成功完成,并返回了结果。

2.处理已完成的Future

        当Future进入已完成状态时,我们可以使用then方法来处理成功的结果,使用catchError方法来处理失败的错误。另外,可以使用async/await来简化异步代码。

        以下是一个创建和使用Future的示例,展示如何处理已完成状态的Future:

Future<String> fetchData() {
  // 创建一个延迟两秒后完成的Future
  return Future.delayed(Duration(seconds: 2), () => 'Data fetched');
}

void main() {
  print('Fetching data...');
  
  fetchData().then((result) {
    // 当Future完成时,处理结果
    print(result);
  }).catchError((error) {
    // 当Future失败时,处理错误
    print('Error: $error');
  });

  print('Waiting for data...');
}

        执行这段代码时,控制台的输出如下:

Fetching data...
Waiting for data...
Data fetched

        在上面的实例中:

1.fetchData函数返回一个在两秒后完成的Future,并返回字符串"Data fetched"。

2.使用then方法处理Future完成时的结果,输出"Data fetched"。

3.使用catchError方法处理Future失败时的错误(示例中未发生错误)。

3.使用async/await

        async/await语法使得处理异步操作更加直观和简洁。以下是同样功能的代码,使用async/await:

Future<void> fetchDataAndPrint() async {
  print('Fetching data...');
  
  try {
    // 使用await等待Future完成
    String result = await fetchData();
    print(result);
  } catch (error) {
    print('Error: $error');
  }

  print('Data fetching completed.');
}

void main() {
  fetchDataAndPrint();
}    

        执行这个代码时,控制台的输出如下:

Fetching data...
Data fetched
Data fetching completed.

        在这个示例中:

1.使用await关键字等待Future完成,并获取其结果。

2.try块用于捕获可能的错误,并在catch块中处理错误。

4.Future的已完成状态的处理

        在Flutter的完成状态中,有失败和成功两种情况。

1.对于成功完成的Future,使用then方法处理完成的Future,或者在async函数中是用await。

2.对于失败完成的Future,使用catchError方法处理失败完成的Future,或者在async函数中使用try/catch。

3.已失败(Completed with an error)
1.概念

        Future的失败状态表示该异步操作已经完成,但由于某种原因失败,并抛出了一个错误。

2.处理失败状态的Future

        当Future进入失败状态时,可以使用catchError方法来处理失败的错误,或者在async/await语法中使用try/catch块来捕获和处理错误。

        以下是一个创建和使用Future的示例,展示如何处理失败状态的Future:

Future<String> fetchData() {
  // 创建一个延迟两秒后失败的Future
  return Future.delayed(Duration(seconds: 2), () => throw 'Failed to fetch data');
}

void main() {
  print('Fetching data...');
  
  fetchData().then((result) {
    // 当Future成功完成时,处理结果
    print(result);
  }).catchError((error) {
    // 当Future失败时,处理错误
    print('Error: $error');
  });

  print('Waiting for data...');
}

        执行这段代码时,控制台的输出如下:

Fetching data...
Waiting for data...
Error: Failed to fetch data

        在上面这个示例中:

1. fetchData函数返回一个在两秒后失败的Future,并抛出字符串"Failed to fetch data"。

2. 使用then方法处理Future成功完成时的结果(在此示例中不会被调用)。

3. 使用catchError方法处理Future失败时的错误,输出"Error: Failed to fetch data"。

3.使用 async/await

        async/await语法使得处理异步操作的失败更加直观和简洁。以下是同样功能的代码,使用async/await:

Future<void> fetchDataAndPrint() async {
  print('Fetching data...');
  
  try {
    // 使用await等待Future完成
    String result = await fetchData();
    print(result);
  } catch (error) {
    // 捕获并处理错误
    print('Error: $error');
  }

  print('Data fetching completed.');
}

void main() {
  fetchDataAndPrint();
}

        执行这个代码时,控制台的输出如下:

Fetching data...
Error: Failed to fetch data
Data fetching completed.

        在这个示例中:

1. 使用await关键字等待Future完成,并获取其结果。

2. try块用于捕获可能的错误,并在catch块中处理错误。

4.捕获和处理错误的最佳实践

        理解和处理Future的失败状态是Flutter异步编程的重要部分。通过使用catchError和try/catch语法,可以有效地捕获和处理异步操作中的错误,从而编写更健壮和稳定的Flutter应用程序。

1.始终捕获错误

        无论使用then和catchError还是async/await,始终确保捕获并处理Future中的错误,以避免未处理的异常。

2.提供用户反馈

        在用户界面上提供适当的反馈,如显示错误消息或提示用户重试操作。

3.记录错误

        在开发和调试过程中,记录错误信息有助于查找和修复问题。

3.创建Future

        创建一个Future非常简单,可以使用Future构造函数、Future.delayed、Future.value和Future.error等方法。

1.使用Future构造函数
Future<String> fetchData() {return Future(() {return 'Data fetched';});
}void main() {fetchData().then((data) {print(data);});
}
2.使用Future.delayed
Future<String> fetchData() {return Future.delayed(Duration(seconds: 2), () {return 'Data fetched';});
}void main() {fetchData().then((data) {print(data);});
}
3.使用Future.value和Future.error
void main() {Future.value('Immediate data').then((data) {print(data);});Future.error('An error occurred').catchError((error) {print(error);});
}

4.处理Future

        处理Future通常有两种方式:使用then和catchError方法,或者使用async/await语法。

1.使用then和catchError
Future<String> fetchData() {return Future.delayed(Duration(seconds: 2), () {return 'Data fetched';});
}void main() {fetchData().then((data) {print(data);}).catchError((error) {print('Error: $error');});
}
2.使用async/await
Future<String> fetchData() async {await Future.delayed(Duration(seconds: 2));return 'Data fetched';
}void main() async {try {String data = await fetchData();print(data);} catch (error) {print('Error: $error');}
}
3.Future的链式调用

        多个Future可以通过链式调用连接在一起,从而依次处理多个异步操作。

Future<void> fetchData() {
  return Future.delayed(Duration(seconds: 2), () {
    print('Step 1: Data fetched');
  }).then((_) {
    return Future.delayed(Duration(seconds: 1), () {
      print('Step 2: Additional data fetched');
    });
  }).then((_) {
    print('Step 3: All steps completed');
  });
}

void main() {
  fetchData();
}

2. Stream

        在Flutter中,Stream用于表示一系列异步数据事件。与Future不同,Stream可以提供多个值而不是单个值。它非常适合处理诸如用户输入、实时数据更新和传感器数据等连续数据流。本文将详细介绍Flutter中`Stream`的基本概念和用法。

1.Stream的两种类型

        1.单订阅Stream(Single-subscription Stream):只能被单个监听器(listener)监听。这种Stream适用于大多数情况。
        2.广播Stream(Broadcast Stream):可以被多个监听器同时监听。这种Stream适用于需要多个订阅者的情况,如事件总线(Event Bus)。

2.创建Stream

        创建Stream有多种方式,常见的包括使用StreamController和异步生成器函数。

1.使用StreamController

        StreamController用于创建和管理Stream。

void main() {// 创建一个StreamControllerfinal controller = StreamController<int>();// 获取Streamfinal stream = controller.stream;// 监听Streamstream.listen((data) {print('Data: $data');}, onDone: () {print('Stream closed');});// 添加数据到Streamcontroller.add(1);controller.add(2);controller.add(3);// 关闭Streamcontroller.close();
}

        执行这个代码时,控制台的输出如下:

Data: 1
Data: 2
Data: 3
Stream closed

2.使用异步生成器函数

        可以使用async*和yield关键字创建Stream。

Stream<int> countStream(int to) async* {for (int i = 1; i <= to; i++) {await Future.delayed(Duration(seconds: 1));yield i;}
}void main() {final stream = countStream(5);stream.listen((data) {print('Data: $data');}, onDone: () {print('Stream closed');});
}

        执行这个代码时,控制台的输出如下:

Data: 1
Data: 2
Data: 3
Data: 4
Data: 5
Stream closed

3.监听Stream

        使用listen方法可以监听Stream,并处理接收到的数据和错误。

stream.listen((data) {print('Data: $data');},onError: (error) {print('Error: $error');},onDone: () {print('Stream closed');},cancelOnError: false, // 当为true时,接收到错误后将取消订阅
);

4.使用StreamBuilder

        在Flutter中,StreamBuilder小部件用于根据Stream构建UI。它会监听Stream并在每次接收到数据时重新构建UI。

Stream<int> countStream(int to) async* {
  for (int i = 1; i <= to; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('StreamBuilder Example'),
      ),
      body: Center(
        child: StreamBuilder<int>(
          stream: countStream(5),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator();
            } else if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            } else if (!snapshot.hasData) {
              return Text('No Data');
            } else {
              return Text('Count: ${snapshot.data}');
            }
          },
        ),
      ),
    );
  }
}

void main() => runApp(MaterialApp(home: MyHomePage()));

        在这个示例中,StreamBuilder监听countStream,并根据Stream的状态更新UI。

5.Stream的高级用法

1.转换Stream

        使用Stream的转换方法可以方便地处理数据,例如使用map方法转换数据:

Stream<int> countStream(int to) async* {for (int i = 1; i <= to; i++) {await Future.delayed(Duration(seconds: 1));yield i;}
}void main() {final stream = countStream(5).map((data) => data * 2);stream.listen((data) {print('Transformed Data: $data');});
}

2.合并Stream

        可以使用StreamGroup来合并多个Stream:

void main() {final stream1 = Stream.fromIterable([1, 2, 3]);final stream2 = Stream.fromIterable([4, 5, 6]);final mergedStream = StreamGroup.merge([stream1, stream2]);mergedStream.listen((data) {print('Merged Data: $data');});
}

6.总结

        Stream在Flutter中是处理异步数据事件的强大工具。通过理解和使用StreamController、异步生成器函数以及StreamBuilder,可以有效地处理和显示连续的数据流。希望本文能帮助你更好地理解和使用Flutter中的Stream。

        Future 表示不会立即完成的计算。普通函数会返回结果,而异步函数则会返回 Future,后者最终会包含结果。Future 会告诉您结果何时准备就绪。

        Stream(流)是一系列异步事件。它类似于异步 Iterable — 流不会在您请求时获取下一个事件,而是在事件准备就绪时告诉您有事件发生。

3.FutureBuilder和StreamBuilder

        FutureBuilder和StreamBuilder是Flutter中用于处理异步数据的两个常用小部件。

1.FutureBuilder

        FutureBuilder用于构建依赖于Future的widget。

FutureBuilder<String>(future: fetchUserOrder(),builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.waiting) {return CircularProgressIndicator();} else if (snapshot.hasError) {return Text('Error: ${snapshot.error}');} else {return Text('Order: ${snapshot.data}');}},
);

2.StreamBuilder

        StreamBuilder用于构建依赖于Stream的widget。

StreamBuilder<int>(stream: countStream(5),builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.waiting) {return CircularProgressIndicator();} else if (snapshot.hasError) {return Text('Error: ${snapshot.error}');} else if (!snapshot.hasData) {return Text('No Data');} else {return Text('Count: ${snapshot.data}');}},
);

相关文章:

Flutter中的异步编程

目录 前言 1. Future 和 async/await 1.Future 1.什么是Future? 2.Flutter的三种状态 1.未完成&#xff08;Uncompleted&#xff09; 1.定义 2.处理未完成的Future 2.已完成(Completed with a value) 1.概念 2.处理已完成的Future 3.使用async/await 4.Fu…...

vue3 路由带传参跳转;刷新后消失。一次性参数使用。

解决vue3 怎么做到路由跳转传参刷新后消失 解决路由跳转传参去除问题 想要跳转后根据参数显示对应的tab&#xff0c;但url传参刷新会持续保留无法重置。 router.replace替换又会导致显示内容为router.replace后的&#xff0c;传参目的丢失。 业务逻辑&#xff1a; 完成对应操作…...

Unity新输入系统结构概览

本文仅作笔记学习和分享&#xff0c;不用做任何商业用途 本文包括但不限于unity官方手册&#xff0c;unity唐老狮等教程知识&#xff0c;如有不足还请斧正 在学习新输入系统之前&#xff0c;我们需要对其构成有个印象 1.输入动作&#xff08;Inputaction&#xff09; 是定义输…...

18104 练习使用多case解题

### 伪代码 1. 读取第1批测试数据的CASE数量。 2. 处理第1批测试数据&#xff0c;计算每个CASE的最小公倍数并输出。 3. 输出“group 1 done”。 4. 处理第2批测试数据&#xff0c;直到遇到两个0&#xff0c;计算每个CASE的最小公倍数并输出。 5. 输出“group 2 done”。 6. 处…...

【AI人工智能】文心智能体 - 你的专属车牌设计师

引言 自AI盛行以来&#xff0c;不断有各种各样的人工智能产品崭露头角。我们逐步跟着不断产生的人工智能来使自己的工作和生活变得更加智能化&#xff01;那么我们是否能够创造一款专属于自己的人工智能产品呢&#xff1f; 文心智能体平台就给我们提供了这样的机会&#xff0c…...

Linux-服务器硬件及RAID配置实验

系列文章目录 提示&#xff1a;仅用于个人学习&#xff0c;进行查漏补缺使用。 1.Linux介绍、目录结构、文件基本属性、Shell 2.Linux常用命令 3.Linux文件管理 4.Linux 命令安装(rpm、install) 5.Linux账号管理 6.Linux文件/目录权限管理 7.Linux磁盘管理/文件系统 8.Linu…...

白屏检测系统的设计与实现

目录 一、 什么是白屏问题&#xff1f;二、 问题分析与拆解2.1 人工判定一个白屏问题的逻辑2.2 自动化判定一个白屏问题的算法思想 三、 白屏检测算法3.1 图像灰度化3.2 图像二值化3.3 计算&#xff08;判定为白屏&#xff09;置信度 四、 白屏检测系统的设计与实现4.1 UI自动化…...

Real-Time Open-Vocabulary Object Detection:使用Ultralytics框架进行YOLO-World目标检测

Real-Time Open-Vocabulary Object Detection&#xff1a;使用Ultralytics框架进行YOLO-World目标检测 前言相关介绍前提条件实验环境安装环境项目地址LinuxWindows 使用Ultralytics框架进行YOLO-World目标检测进行训练进行预测进行验证 扩展目标跟踪设置提示 参考文献 前言 由…...

区块链用什么编程语言实现?

. 主流区块链的开发语言主要有&#xff1a;C、Go、Java、Rust、C#。 C使用率最高&#xff0c;其次是Go&#xff0c;很少有人用python开发区块链。...

【网络编程】UDP通信基础模型实现

udpSer.c #include<myhead.h> #define SER_IP "192.168.119.143" #define SER_PORT 7777 int main(int argc, const char *argv[]) {//1.创建int sfd socket(AF_INET,SOCK_DGRAM,0);if(sfd -1){perror("socket error");return -1;}//2.连接struct…...

Docker Compose 常用命令详解

Docker Compose 常用命令详解 Docker Compose 是 Docker 官方编排工具之一&#xff0c;用于定义和运行多容器 Docker 应用程序。通过 docker-compose.yml 文件&#xff0c;开发者可以轻松管理服务、网络、卷以及各服务之间的依赖关系。以下将介绍一些常用的 Docker Compose 命…...

超级外链工具,可发9600条优质外链

超级外链工具&#xff0c;是一款在线全自动化发外链的推广工具。使用本工具可免费为网站在线批量增加外链&#xff0c;大大提高外链发布工作效率&#xff0c;是广大草根站长们必备的站长工具。 外链工具只是网站推广的辅助工具&#xff0c;一般适用于短时间内无法建设大量外链…...

VisionPro二次开发学习笔记13-使用CogToolBlock进行图像交互

该程序演示了如何使用CogToolBlock进行图像交互. 从vpp文件中加载一个ToolBlock。 用户可以通过应用程序窗体上的数字增减控件修改ToolBlock输入端子的值。 用户还可以从coins.idb或采集FIFO中选择图像。 “运行一次”按钮执行以下操作&#xff1a; 获取下一个图像或读取下一…...

比特币价格分析:市场重置完成,下一个目标:70,000 美元

比特币再次处于关键支撑位&#xff0c;面临可能影响其短期前景的关键考验。分析师们正密切关注比特币是否重复熟悉的模式&#xff0c;暗示可能出现重大走势。 OKNews分析师Josh表示&#xff0c;比特币一直处于看跌趋势&#xff0c;正如 4 日图上的超级趋势指标所示。这种趋势的…...

大模型笔记5 Extractive QA任务评估

目录 Extractive QA任务评估 Extractive QA评测指标 precision, recall, f1 ROUGE 划分训练与评估数据集 token位置评估 单个token位置评估 输入label的token位置 预测token位置 评估 Wandb 共享机器同时登录 样本类别平衡 标记token label时对窗口进行筛选 训练…...

RCE绕过方式

目录 小于8个字符突破限制 无字母数字执行 php7的做法 php5的思考 PHP5shell 深入理解glob通配符 构造POC&#xff0c;执行任意命令 无参数读文件和RCE总结 代码解读 构造. 另一种构造方法 小于8个字符突破限制 但也只能执行一些非常短的命令&#xff0c;没有什么意义…...

Flutter 电视投屏模块

前言 村里的老人说:“珍爱生命,远离低头族。“ 之前开发的一个 DIM 项目 Tarsier,里面有一个分享视频的功能,同时包含在线视频播放、电视直播等。 考虑到用户在手机上看视频的体验问题,需要增加一个投屏功能,以便用户可以电影、电视直播等投到电视上用大屏幕观看。 用…...

【机器学习】卷积神经网络简介

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 卷积神经网络简介1. 引言2. CNN的基本概念2.1 什么是卷积神经网络2.2 CNN与传统…...

时间函数链接函数等

1. 2.top相当于windows任务管理器 3.命令模式下不加冒号20G直接跳转行数 4. 相当于strcat 5.:13,15y 13行到15行复制 6. Ctrl 右 】是追踪命令 7. vi off_t -t看类型 8. qa关闭所有 9.gg 移动最前面 GG移动到最后面 10.终端中的全选命令1. 使用快捷键&…...

Android控件(示例)

在Android应用程序中&#xff0c;界面由布局和组件组成。布局相当于框架&#xff0c;而控件则是框架里面的内容。了解过Android布局后&#xff0c;如果要设计ui界面&#xff0c;还需要了解和掌握各个控件的应用。 一个界面的设计&#xff0c;先从创建容器开始&#xff0c;再向…...

别再乱用分支了!Flowable四种网关(排他/并行/包容/事件)实战选型指南

Flowable四大网关实战选型&#xff1a;从混乱到精准的决策艺术当你在设计一个请假审批流程时&#xff0c;是否遇到过这样的困惑&#xff1a;部门经理审批后需要同时通知HR和财务&#xff0c;但某些特殊情况下又需要跳过财务直接归档&#xff1f;这种看似简单的业务需求&#xf…...

长期使用Taotoken聚合服务对项目月度账单的可预测性提升

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 长期使用Taotoken聚合服务对项目月度账单的可预测性提升 在AI驱动的项目开发与运营中&#xff0c;成本控制与预算规划是团队管理者…...

差分隐私GDP机制紧密度量化:从隐私剖面到∆度量的实践指南

1. 差分隐私GDP机制&#xff1a;从理论到实践&#xff0c;如何量化隐私保护紧密度在差分隐私&#xff08;Differential Privacy, DP&#xff09;的实际部署中&#xff0c;尤其是在机器学习的隐私保护训练&#xff08;如DP-SGD&#xff09;场景里&#xff0c;我们常常面临一个核…...

Hindsight测试策略:单元测试、集成测试和端到端测试

Hindsight测试策略&#xff1a;单元测试、集成测试和端到端测试 【免费下载链接】hindsight Hindsight: Agent Memory That Learns 项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight Hindsight作为一款专注于Agent Memory的开源项目&#xff0c;其可…...

基于雷达与光敏传感器的低功耗智能窗防设备设计与实现

1. 项目概述&#xff1a;一个基于雷达与光敏的智能窗防设备几年前&#xff0c;我因为一次短暂的出差&#xff0c;家里空置了几天&#xff0c;回来后就一直琢磨着怎么给家里的窗户加点“动静”。市面上的智能安防摄像头固然好&#xff0c;但要么需要复杂的布线&#xff0c;要么云…...

微信小程序项目实战:从npm安装Vant Weapp到解决样式冲突的完整避坑指南

微信小程序工程化实战&#xff1a;Vant Weapp集成与样式冲突解决方案全解析 第一次在小程序里引入Vant Weapp时&#xff0c;我对着满屏错位的组件样式发呆了半小时——原本优雅的按钮变成了扭曲的色块&#xff0c;表单元素叠在一起像抽象画。这不是个例&#xff0c;根据社区反…...

超低功耗电池电压监控电路设计:从LM324到LPV324的硬件方案优化

1. 项目概述与核心需求解析在捣鼓各种电池供电的电子设备时&#xff0c;无论是自己做的无线传感器节点、便携式小工具&#xff0c;还是给孩子改装的玩具&#xff0c;有一个问题总是绕不开&#xff1a;你怎么知道电池快没电了&#xff1f;总不能每次都等到设备彻底罢工&#xff…...

AutoWall终极指南:如何在Windows上轻松设置炫酷动态壁纸

AutoWall终极指南&#xff1a;如何在Windows上轻松设置炫酷动态壁纸 【免费下载链接】AutoWall &#x1f30c; Live wallpapers on Windows 7/8/10/11 using open-source wallpaper engine 项目地址: https://gitcode.com/gh_mirrors/au/AutoWall 厌倦了千篇一律的静态桌…...

AB包相关知识

Lua与AB包/Addressables以及YooAsset 摘自千问&#xff1a; Lua 是菜谱&#xff08;逻辑&#xff09;&#xff1a;决定了菜怎么做&#xff0c;味道如何。因为你需要随时换菜谱&#xff08;热更新&#xff09;&#xff0c;所以菜谱不能死板地印在墙上&#xff08;编译进主包&a…...

基于PIC32单片机实现Android USB音频转SPDIF输出的DIY方案

1. 项目概述&#xff1a;为Android设备打造一个高保真SPDIF音频接口作为一名长期折腾嵌入式音频和家庭影院的玩家&#xff0c;我经常遇到一个痛点&#xff1a;手头那些性能不错的Android手机或平板&#xff0c;其内置的3.5mm耳机孔或者USB-C口的音频输出质量&#xff0c;在连接…...