Flutter实现局部刷新的几种方式

news2024/9/23 17:23:03

目录

前言

1.局部刷新的重要性

1.概念

2.重要性

2.局部刷新实现的几种方式

1.使用setState方法进行局部刷新

2.使用StatefulWidget和InheritedWidget局部刷新UI

3.ValueNotifier和ValueListenableBuilder

4.StreamBuilder

5.Provider

6.GetX

7.使用GlobalKey


前言

       在 Flutter 中,状态管理指的是如何管理和更新应用中的数据状态,并且根据状态的变化来更新 UI。有效的状态管理能够帮助开发者创建更高效、更可维护的应用。

        setState是 Flutter 中最基本的状态管理方法,当状态发生变更的时候,会通知框架重新构建UI。当然我们知道当我们调用setState方法的时候,页面会重绘,当页面布局比较复杂的时候,有时候我们仅仅需要更新某个单独的UI,这个时候如果使用setState方法,则会有比较大的性能消耗去重绘当前页面UI.

        那么Flutter中有哪些方法可以局部刷新UI呢,这篇博客列举了Flutter实现局部刷新的几种方式。

1.局部刷新的重要性

1.概念

        局部刷新指的是只刷新界面的一部分,而不是整个页面。这样可以提高性能和用户体验。

2.重要性

  1. 避免不必要的重绘,提高性能
  2. 提供更流畅的用户体验
  3. 减少资源消耗

2.局部刷新实现的几种方式

1.通过setState局部刷新

        setState是Flutter 中最常用的状态管理方法,用于通知框架状态发生变化,导致界面重建。

        我们创建Flutter工程的时候,系统默认生成的计时器的例子,就是setState局部刷新的例子。

import 'package:flutter/material.dart';

class StatePartialRefreshPage extends StatefulWidget {
  const StatePartialRefreshPage({super.key});
  @override
  State<StatePartialRefreshPage> createState() =>
      _StatePartialRefreshPageState();
}

class _StatePartialRefreshPageState extends State<StatePartialRefreshPage> {
  int _count = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          "setState局部刷新",
          style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
        ),
      ),
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            '您点击了$_count次',
            style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
          ),
          const SizedBox(
            height: 20,
          ),
          FilledButton(
              onPressed: () {
                setState(() {
                  _count++;
                });
              },
              child: const Icon(Icons.add)),
        ],
      )),
    );
  }
}

        图1.setState局部刷新

         当页面比较简单的时候,可以直接使用setState方法局部刷新UI。

        使用场景:简单的状态变化,如按钮点击计数、开关状态等。

        注意事项:

  1. 频繁调用 setState 可能导致性能问题
  2. 避免在 build 方法中调用 setState 

2.使用StatefulWidget和InheritedWidget局部刷新UI

        StatefulWidget 是具有状态的组件,InheritedWidget 用于在组件树中共享数据。

        当我们需要共享数据的时候,可以考虑StatefulWidget和InheritedWidget局部刷新UI.

        完整代码如下:

        图2.共享数据的方式刷新UI

import 'package:flutter/material.dart';

class MyInheritedWidget extends InheritedWidget {
  final int counter;
  const MyInheritedWidget({
    super.key,
    required this.counter,
    required super.child,
  });
  @override
  bool updateShouldNotify(covariant InheritedWidget oldWidget) {
    return true;
  }
  static MyInheritedWidget? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
  }
}

class InheritedWidgetPage extends StatefulWidget {
  final String title;
  const InheritedWidgetPage({super.key, required this.title});

  @override
  State<InheritedWidgetPage> createState() => _InheritedWidgetPageState();
}

class _InheritedWidgetPageState extends State<InheritedWidgetPage> {
  int counter = 0;
  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MyInheritedWidget(
      counter: counter,
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(child: Column(
          children: [
            const Divider(),
            const CounterDisplay(),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _incrementCounter,
              child: const Text('add'),
            ),
          ],
        ),),
      ),
    );
  }
}

class CounterDisplay extends StatelessWidget {
  const CounterDisplay({super.key});
  @override
  Widget build(BuildContext context) {
    final inheritedWidget = MyInheritedWidget.of(context);
    return Text('点击次数: ${inheritedWidget?.counter}');
  }
}

        这种方式主要使用场景如下:组件树中共享状态时,如主题、语言设置等。

        优点就是数据共享方便,代码简介

        缺点就是使用复杂,性能可能收到影响

3.ValueNotifier和ValueListenableBuilder

        ValueNotifier 是一个简单的状态管理工具,ValueListenableBuilder 用于监听 ValueNotifier 的变化。

        使用方法也非常简单:

        1.实例化ValueNotifier

        2.要监听的Widget对象是用ValueListenableBuilder包裹起来

        3.事件触发数据的变更方法

        这种方式和前几种方式比较非常的简单易容,性能也很高

        缺点:只能处理简单的状态变化

        完整的代码如下:

import 'package:flutter/material.dart';

class ValueNotifierPage extends StatefulWidget {
  final String title;
  const ValueNotifierPage({super.key, required this.title});

  @override
  State<ValueNotifierPage> createState() => _ValueNotifierPageState();
}

class _ValueNotifierPageState extends State<ValueNotifierPage> {

  final ValueNotifier<int> _counter = ValueNotifier<int>(0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(
          child: ValueListenableBuilder<int>(
            valueListenable: _counter,
            builder: (context, value, child) {
              return Text(
                '您点击了$value次',
                style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
              );
            },
          )
        ),
        floatingActionButton: FloatingActionButton(
          child: const Icon(Icons.add),
          onPressed: () {
            _counter.value ++;
          },
        )
    );
  }
}

4.StreamBuilder

        Stream是一种用于传递异步事件的对象,可以通过StreamController发送事件。在需要刷新UI的地方,可以发送一个事件到Stream,然后使用StreamBuilder监听该Stream,当收到新的事件时,StreamBuilder会自动重新构建UI。这种方式适用于需要监听多个异步事件的情况。

        当我们需要处理异步数据流,如网络请求、实时数据等的时候,可以考虑使用StreamBuilder。例如在下面的例子中,我们写了一个模拟网络请求的异步方法,当网络请求没返回正确结果的时候,我们可以加载进度条。

        这种方式的优点就是可以对异步请求进行更加精准的控制,例如网络请求的状态等。却迪奥就是复杂度比较高,可能需要更多的代码。        

        完整的代码如下:

import 'dart:async';
import 'package:flutter/material.dart';

class StreamBuilderRefreshUIPage extends StatefulWidget {
  final String title;
  const StreamBuilderRefreshUIPage({super.key, required this.title});

  @override
  State<StreamBuilderRefreshUIPage> createState() =>
      _StreamBuilderRefreshUIPageState();
}

class _StreamBuilderRefreshUIPageState extends State<StreamBuilderRefreshUIPage> {
  late Future<String> _data;

  Future<String> fetchData() async {
    // 模拟网络请求延迟
    await Future.delayed(const Duration(seconds: 2));
    // 返回模拟数据
    return 'Hello, Flutter!';
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _data = fetchData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: FutureBuilder<String>(
          future: _data,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return const CircularProgressIndicator();
            } else if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            } else {
              return Text('Data: ${snapshot.data}');
            }
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: fetchData,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

5.Provider

       Provider 是 Flutter 推荐的状态管理解决方案,Consumer 用于读取和监听状态。

        我们还以定时器为例。

        1.首先我们导入Provider.

provider: ^6.1.2

        2.自定义ChangeNotifier类。

        ChangeNotifier 是 Flutter SDK 中的一个简单的类。它用于向监听器发送通知。换言之,如果被定义为 ChangeNotifier,你可以订阅它的状态变化。(这和大家所熟悉的观察者模式相类似)。

        在我们要实现的代码中,有两个变量_counter1和_counter2.代码定义如下:

class CounterModel extends ChangeNotifier {
  int _counter1 = 0;
  int _counter2 = 0;
  void addCounter1(){
    debugPrint('counter:$_counter1');
    _counter1 += 1;
    notifyListeners();
  }
  void addCounter2(){
    debugPrint('counter:$_counter2');
    _counter2 += 1;
    notifyListeners();
  }
}

        3.使用Customer把我们要刷新的Widget包裹起来

            Consumer<CounterModel>(
              builder: (context, counterModel, child) {
                return Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Text('计数器1个数: ${counterModel._counter1}'),
                    ElevatedButton(onPressed: (){
                      counterModel.addCounter1();
                    }, child: const Icon(Icons.add),),
                  ],
                );
              },
            ),

        4.完整代码如下:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class ProviderRefreshPage extends StatefulWidget {
  final String title;
  const ProviderRefreshPage({super.key, required this.title});

  @override
  State<ProviderRefreshPage> createState() => _ProviderRefreshPageState();
}

class CounterModel extends ChangeNotifier {
  int _counter1 = 0;
  int _counter2 = 0;
  void addCounter1(){
    debugPrint('counter:$_counter1');
    _counter1 += 1;
    notifyListeners();
  }
  void addCounter2(){
    debugPrint('counter:$_counter2');
    _counter2 += 1;
    notifyListeners();
  }
}

class _ProviderRefreshPageState extends State<ProviderRefreshPage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            const SizedBox(height: 10,), // 添加一些间距
            const Divider(),
            const Text('计数器实例',style: TextStyle(fontSize: 12,fontWeight: FontWeight.bold),),
            Consumer<CounterModel>(
              builder: (context, counterModel, child) {
                return Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Text('计数器1个数: ${counterModel._counter1}'),
                    ElevatedButton(onPressed: (){
                      counterModel.addCounter1();
                    }, child: const Icon(Icons.add),),
                  ],
                );
              },
            ),

            Consumer<CounterModel>(
              builder: (context, counterModel, child) {
                return Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Text('计数器1个数: ${counterModel._counter2}'),
                    ElevatedButton(onPressed: (){
                      counterModel.addCounter2();
                    }, child: const Icon(Icons.add),),
                  ],
                );
              },
            ),
            const Divider(height: 20,),
          ],
        ),
      ),
    );
  }
}

6.GetX

        我们还可以使用GetX实现UI的局部刷新。

        首先安装GetX:

get: ^4.6.6

        然后我们把变量封装在GetxController中.

class CounterManagerController extends GetxController {
  final counter1 = 0.obs;
  final counter2 = 0.obs;
  void incrementCount1() {
    counter1.value++;
  }
  void incrementCount2() {
    counter2.value++;
  }
}

        再使用Obx把需要显示逻辑的Widget包裹起来。

Obx(()=> Text('计数器1个数: ${controller.counter2.value}'))

        完整的代码如下:

import 'package:flutter/material.dart';
import 'package:get/get.dart';


class CounterManagerController extends GetxController {
  final counter1 = 0.obs;
  final counter2 = 0.obs;
  void incrementCount1() {
    counter1.value++;
  }
  void incrementCount2() {
    counter2.value++;
  }
}

class GetXRefreshUIPage extends StatelessWidget {
  final String title;
  const GetXRefreshUIPage({super.key, required this.title});

  @override
  Widget build(BuildContext context) {
    final CounterManagerController controller = Get.put(CounterManagerController());
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            const SizedBox(
              height: 10,
            ), // 添加一些间距
            const Divider(),
            const Text(
              '计数器实例',
              style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Obx(()=> Text('计数器1个数: ${controller.counter1.value}')),
                ElevatedButton(
                  onPressed: () {
                    controller.incrementCount1();
                  },
                  child: const Icon(Icons.add),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Obx(()=> Text('计数器1个数: ${controller.counter2.value}')),
                ElevatedButton(
                  onPressed: () {
                    controller.incrementCount2();
                  },
                  child: const Icon(Icons.add),
                ),
              ],
            ),
            const Divider(
              height: 20,
            ),
          ],
        ),
      ),
    );
  }
}

        当然GetX中实现局部刷新的方式还有其它几种写法,大家可以看一下它的文档。这里只是提供了其中的一种实现思路。

7.通过GlobalKey局部刷新

        上述三种实现方式都是通过框架实现的,如果你不想导入这个框架,我们可以使用GlobalKey来实现UI的局部刷新功能。

        在整个应用程序中是唯一的Key GlobalKey可以唯一标识元素,GlobalKey提供了对这些元素相关联的访问,比如BuildContext。对于StatefulWidgets,GlobalKey也提供对State的访问。

       在我们的计时器的demo中,如果我们通过GlobalKey的方式局部刷新UI,首先我们把要局部刷新的Widget提出来,单独封装成一个组件。

        完整代码如下,我们封装要局部刷新的Widget,并且提供一个刷新内部数据的接口,onPressed.

class CounterText extends StatefulWidget {
  const CounterText(Key key) : super(key: key);
  @override
  State<StatefulWidget> createState() {
    return CounterTextState();
  }
}

class CounterTextState extends State<CounterText> {
  String _text="0";

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(_text,style: const TextStyle(fontSize: 20),),
    );
  }
  void onPressed(int count) {
    setState(() {
      _text = count.toString();
    });
  }
}

        然后在我们的主界面实例化GlobaKey:

  int _count   = 0;
  int _count2  = 0;
  GlobalKey<CounterTextState> textKey = GlobalKey();
  GlobalKey<CounterTextState> textKey2 = GlobalKey();    

            在需要刷新UI的事件中,通过GlobalKey调用上一步提供的接口,刷新即可。

        完整代码如下:

import 'package:flutter/material.dart';

class GlobalKeyRefreshPage extends StatefulWidget {
  final String title;
  const GlobalKeyRefreshPage({super.key, required this.title});

  @override
  State<GlobalKeyRefreshPage> createState() => _GlobalKeyRefreshPageState();
}

class _GlobalKeyRefreshPageState extends State<GlobalKeyRefreshPage> {
  int _count   = 0;
  int _count2  = 0;
//包裹你定义的需要更新的weight
  GlobalKey<CounterTextState> textKey = GlobalKey();
  GlobalKey<CounterTextState> textKey2 = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title:  Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            const SizedBox(
              height: 10,
            ), // 添加一些间距
            const Divider(),
            const Text(
              '计数器实例',
              style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                CounterText(textKey),
                ElevatedButton(
                  onPressed: () {
                    _count++;
                    textKey.currentState?.onPressed(_count);
                  },
                  child: const Icon(Icons.add),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                CounterText(textKey2),
                ElevatedButton(
                  onPressed: () {
                    _count2++;
                    textKey2.currentState?.onPressed(_count2);
                  },
                  child: const Icon(Icons.add),
                ),
              ],
            ),
            const Divider(
              height: 20,
            ),
          ],
        ),
      ),
    );
  }
}


class CounterText extends StatefulWidget {
  const CounterText(Key key) : super(key: key);
  @override
  State<StatefulWidget> createState() {
    return CounterTextState();
  }
}

class CounterTextState extends State<CounterText> {
  String _text="0";

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(_text,style: const TextStyle(fontSize: 20),),
    );
  }
  void onPressed(int count) {
    setState(() {
      _text = count.toString();
    });
  }
}

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

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

相关文章

【PyQt】

PyQT5线程基础&#xff08;2&#xff09; 线程案例案例一案例二 线程案例 案例一 案例一代码通过线程实现点击按钮向线程传输地址&#xff0c;程序等待20秒后&#xff0c;返回结果。 通过QtDesigner创建如下图所示的界面ui&#xff0c;并用UIC工具转成对应的py文件。 Ui_tes…

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(十四)-无人机操控关键绩效指标(KPI)框架

引言 本文是3GPP TR 22.829 V17.1.0技术报告&#xff0c;专注于无人机&#xff08;UAV&#xff09;在3GPP系统中的增强支持。文章提出了多个无人机应用场景&#xff0c;分析了相应的能力要求&#xff0c;并建议了新的服务级别要求和关键性能指标&#xff08;KPIs&#xff09;。…

GEO数据挖掘从数据下载处理质控到差异分析全流程分析步骤指南

综合的教学视频介绍 GEO数据库挖掘分析作图全流程每晚11点在线教学直播录屏回放视频&#xff1a; https://www.bilibili.com/video/BV1rm42157CT/ GEO数据从下载到各种挖掘分析全流程详解&#xff1a; https://www.bilibili.com/video/BV1nm42157ii/ 一篇今年近期发表的转…

技术成神之路:设计模式(六)策略模式

1.介绍 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一系列算法&#xff0c;封装每一个算法&#xff0c;并使它们可以相互替换。策略模式使得算法的变化独立于使用算法的客户端。 2.主要作用 策略模式的主要作用是将算法或行为…

算法思想总结:字符串

一、最长公共前缀 . - 力扣&#xff08;LeetCode&#xff09; 思路1&#xff1a;两两比较 时间复杂度mn 实现findcomon返回两两比较后的公共前缀 class Solution { public:string longestCommonPrefix(vector<string>& strs) {//两两比较 string retstrs[0];size…

2.生产者核心流程总结

目录 概述 概述 生产者核心流程总结&#xff0c;根据流程总结出生产者的调优流程及生产者修改配置的文档地址&#xff0c;有以上两点&#xff0c;即可完成生产者优化。 注意&#xff1a;下面的都是生产者环节调优的点。 一条消息经过序例化后划分至 broker 上的哪一个分区消息…

Springboot + JWT 的 Token 登录验证

目录 项目结构 一、 引入依赖 二、自定义Auth认证注解 三、 编写登录拦截器 四、定义跨域拦截器 五、 定义全局异常处理器 六、定义工具类 1. 统一错误状态码 2.统一响应类 3.Token工具类 七、 编写实体类 八、 定义控制器 1.定义登录控制器类 2 定义报错处理器 …

vscode编译环境配置-golang

1. 支持跳转 如果单测函数上方不显示run test | debug test&#xff0c;需要安装Code Debugger&#xff08;因为以前的go Test Explorer不再被维护了&#xff09; 2. 单测 指定单个用例测试 go test -v run TestXXXdlv 调试 需要安装匹配的go版本和delve版本&#xff08;如…

6.S081的Lab学习——Lab11: Network

文章目录 前言Network提示&#xff1a;实现e1000_transmit的一些提示&#xff1a;实现e1000_recv的一些提示&#xff1a; 解析 总结 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招。打算尝试6.S081&#xff0c;将它的Lab逐一实现&#xff0c;并记录期间心酸历程。 代码下…

Go-知识测试-性能测试分析工具-benchstat

Go-知识测试-性能测试分析工具-benchstat benchmark 结果benchstat确认 benchstat 已安装确认 GOPATH 和 GOBIN将 $GOPATH/bin 添加到 PATH验证安装检查安装路径 使用 传送门&#xff1a;Go-知识测试-性能测试 benchmark 结果 benchmark 测试是实际项目中经常使用的测试方法&a…

飞凌全志T527开发板U-Boot添加自定义菜单

昨日&#xff0c;终于收到了心心念念的飞凌OK-T527开发板&#xff0c;板子很漂亮&#xff0c;外设丰富&#xff0c;性能强悍&#xff0c;T527创新性地使用了RISC-V架构的协处理器&#xff0c;后期值得研究一下异核的使用&#xff1a; 有趣的是&#xff0c;板子上电&#xff0c;…

智能制造 v3.13.16 发布,ERP、MES 更新

智能制造一体化管理系统 [SpringBoot2 - 快速开发平台]&#xff0c;适用于制造业、建筑业、汽车行业、互联网、教育、政府机关等机构的管理。包含文件在线操作、工作日志、多班次考勤、CRM、ERP 进销存、项目管理、EHR、拖拽式生成问卷、日程、笔记、工作计划、行政办公、薪资模…

0.单片机工作原理

文章目录 最小系统 单片机芯片 时钟电路 复位电路 电源 最小系统 单片机芯片 本次51单片机的芯片为&#xff1a;STC89C52 Flash(闪存)程序存储器&#xff1a;存储程序的空间 SRAM&#xff1a;数据存储器&#xff0c;可用于存放程序执行的中间结果和过程数据 DPTR&#xff1a;…

某客户报表系统Oracle数据库挂起问题分析处理

某客户报表系统Oracle数据库挂起问题分析处理 一、概要 某客户报表系统Oracle数据库在3月5号、6号均出现一节点实例短暂挂起现象&#xff0c;挂起现象有两种&#xff0c;第一是普通用户不能登录数据库&#xff0c;第二是sys用户可以登录数据库&#xff0c;但是做简单的select查…

C判断一个点在三角形上

背景 鼠标操作时&#xff0c;经常要判断是否命中显示控件&#xff0c;特开发此算法快速判断。 原理 三角形三等分点定理是指在任意三角形ABC中&#xff0c;可以找到三个点D、E和F&#xff0c;使得线段AD、BE和CF均等分三角形ABC。 这意味着三个等分点分别位于三个边界上&…

数据湖表格式 Hudi/Iceberg/DeltaLake/Paimon TPCDS 性能对比(Spark 引擎)

当前&#xff0c;业界流行的集中数据湖表格式 Hudi/Iceberg/DeltaLake&#xff0c;和最近出现并且在国内比较火的 Paimon。我们现在看到的很多是针对流处理场景的读写性能测试&#xff0c;那么本篇文章我们将回归到大数据最基础的场景&#xff0c;对海量数据的批处理查询。本文…

具身大模型研究综述

源自&#xff1a;哈工大SCIR 作者&#xff1a;陈一帆&#xff0c;张宇驰&#xff0c;孙楚芮&#xff0c;冯怀绪&#xff0c;宋浩&#xff0c;王寄哲 指导老师&#xff1a;张伟男 注&#xff1a;若出现无法显示完全的情况&#xff0c;可 V 搜索“人工智能技术与咨询”查看完整…

什么叫图像的双边滤波,并附利用OpenCV和MATLB实现双边滤波的代码

双边滤波&#xff08;Bilateral Filtering&#xff09;是一种在图像处理中常用的非线性滤波技术&#xff0c;主要用于去噪和保边。它在空间域和像素值域上同时进行加权&#xff0c;既考虑了像素之间的空间距离&#xff0c;也考虑了像素值之间的相似度&#xff0c;从而能够有效地…

赛氪网荣获2024年中国高校计算机教育大会合作伙伴荣誉

2024年7月13日&#xff0c;在黑龙江哈尔滨召开的“2024年中国高校计算机教育大会&#xff08;CCEC2024&#xff09;”&#xff0c;环球赛乐&#xff08;北京&#xff09;科技有限公司(以下简称”赛氪网“)凭借其在高等教育与科技创新领域的卓越贡献&#xff0c;荣幸地获得了本次…

SpringBoot详细解析

1.什么是springboot springboot也是spring公司开发的一款框架。为了简化spring项目的初始化搭建的。那么spring对应springboot有什么缺点呢&#xff1f; spring项目搭建的缺点: 配置麻烦依赖tomcat启动慢 2.springboot的特点 自动配置 Spring Boot的自动配置是一个运行时&…