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

kotlin和MVVM的结合使用总结(二)

MVVM 架构详解

核心组件:ViewModel 和 LiveData

在 Android 中,MVVM 架构主要借助 ViewModel 和 LiveData 来实现。ViewModel 负责处理业务逻辑,而 LiveData 则用于实现数据的响应式更新。

ViewModel 的源码分析

ViewModel 的核心逻辑在 ViewModelStore 类中。ViewModelStore 是一个存储 ViewModel 的容器,内部使用 HashMap 来存储不同的 ViewModel 实例。以下是 ViewModelStore 的关键代码:

public class ViewModelStore {private final HashMap<String, ViewModel> mMap = new HashMap<>();final void put(String key, ViewModel viewModel) {ViewModel oldViewModel = mMap.put(key, viewModel);if (oldViewModel != null) {oldViewModel.onCleared();}}final ViewModel get(String key) {return mMap.get(key);}public final void clear() {for (ViewModel vm : mMap.values()) {vm.onCleared();}mMap.clear();}
}

ViewModel 利用 ViewModelStore 保证在配置变更(如屏幕旋转)时数据不丢失,并且将业务逻辑与 ActivityFragment 分离,提高了代码的可维护性和可测试性。

LiveData 的源码分析

LiveData 基于观察者模式,通过 observe 方法添加观察者,当数据变化时,会调用 Observer 的 onChanged 方法更新 UI。

与 MVC 架构对比

MVC 架构的问题

在 MVC 架构中,Activity 既充当 View 又充当 Controller。在 Android 中,Activity 继承自 AppCompatActivity,其源码中包含大量视图初始化和事件处理代码,使得 Activity 变得复杂。例如:

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.button).setOnClickListener(v -> {// 处理点击事件});}
}

与 MVVM 相比,MVC 没有明确的职责划分,导致代码耦合度高,难以维护和扩展。

与 MVP 架构对比

MVP 架构的特点

MVP 中 Presenter 与 View 通过接口交互。Presenter 持有 View 接口的引用,在更新视图时调用接口方法。以下是一个简单的示例:

// View 接口
public interface MainView {void showData(String data);
}// Presenter 类
public class MainPresenter {private MainView view;public MainPresenter(MainView view) {this.view = view;}public void loadData() {// 模拟加载数据String data = "Hello, MVP!";view.showData(data);}
}

而 MVVM 采用数据绑定,ViewModel 无需持有 View 的引用,降低了耦合度,使得代码更加灵活和易于维护。

面试扩展:

MVVM 架构与其他架构区别

  1. 请详细阐述 MVVM、MVC 和 MVP 架构在数据绑定机制上的差异,并说明这种差异如何影响代码的可维护性和扩展性。
    回答

    • MVVM:在 Android 中借助 LiveData 实现数据绑定,以 LiveData 源码为例,它基于观察者模式,通过 observe 方法添加观察者,内部维护 mVersion 和 ObserverWrapper 的 mLastVersion 来控制数据分发。数据变化时,LiveData 会遍历观察者调用 onChanged 方法更新 UI,使得 View 和 ViewModel 之间的数据同步自动化,减少手动更新代码,提高可维护性与扩展性。例如在复杂 UI 界面中,数据更新无需在多处手动操作视图。
    • MVC:如在 Android 里 Activity 常兼具 View 和 Controller 职责,在 Activity 源码中,大量视图初始化和事件处理代码混杂,在更新视图时需手动在 Controller 部分(如 Activity 中的业务逻辑代码)编写更新视图的代码,这导致代码耦合度高,可维护性差。例如一个界面有多个视图需更新,代码中会有多处重复的视图更新逻辑,不利于扩展新功能。
    • MVP:Presenter 通过接口与 View 交互,更新视图时 Presenter 手动调用 View 接口方法。从代码结构看,Presenter 持有 View 引用,若业务逻辑复杂,Presenter 会变得臃肿,可维护性降低。且当 View 层变化时,Presenter 中调用 View 接口方法的代码也需大量修改,扩展性不佳。比如更换了视图框架,Presenter 中更新视图的方法基本都要调整。
  2. 从架构组件的生命周期角度,分析 MVVM 与 MVP 架构的不同。
    回答

    • MVVM:ViewModel 的生命周期由 ViewModelStore 和 ViewModelProvider 管理。ViewModelProvider 从 ViewModelStore 中创建或获取 ViewModel 实例,在配置变更(如屏幕旋转)时,ViewModel 实例不销毁,保证数据存储。而 LiveData 具有生命周期感知能力,通过 LifecycleOwner 控制观察者的注册与注销,只有当 LifecycleOwner 处于活跃状态(如 STARTED 或 RESUMED)时,观察者才会接收数据更新,避免内存泄漏等问题。
    • MVP:Presenter 与 View 通过接口交互,Presenter 持有 View 引用。但 Presenter 本身没有很好的生命周期管理机制,在配置变更时,若不妥善处理,Presenter 可能会持有旧的 View 引用,导致内存泄漏。例如在屏幕旋转时,若没有正确处理 Presenter 与 View 的关系,可能会出现空指针异常等问题。

LiveData 数据倒灌的源码级别分析

数据倒灌的原因

LiveData 内部维护了一个 mVersion 和 START_VERSIONmVersion 表示 LiveData 数据的版本号,每次数据更新时 mVersion 会递增。ObserverWrapper 是 Observer 的包装类,其中的 mLastVersion 记录了观察者最后一次接收到数据的版本号。

// LiveData 关键代码
private static abstract class ObserverWrapper {final Observer<? super T> mObserver;boolean mActive;int mLastVersion = START_VERSION;ObserverWrapper(Observer<? super T> observer) {mObserver = observer;}// ...
}

当新的观察者注册时,LiveData 会检查 mLastVersion 和 mVersion,如果 mLastVersion 小于 mVersion,则会将数据发送给观察者,从而导致数据倒灌。

解决方法原理

以 SingleLiveEvent 为例,它通过一个标志位 mPending 来控制数据是否已被消费。

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;import java.util.concurrent.atomic.AtomicBoolean;public class SingleLiveEvent<T> extends MutableLiveData<T> {private final AtomicBoolean mPending = new AtomicBoolean(false);@Overridepublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {super.observe(owner, t -> {if (mPending.compareAndSet(true, false)) {observer.onChanged(t);}});}@Overridepublic void setValue(T value) {mPending.set(true);super.setValue(value);}@Overridepublic void postValue(T value) {mPending.set(true);super.postValue(value);}
}

当数据更新时,mPending 设为 true,观察者接收到数据后将其设为 false,确保数据只被消费一次。

面试扩展:

  1. 请描述 LiveData 数据倒灌产生的原因,并给出至少两种基于源码层面的解决方案。
    回答
    • 原因:从 LiveData 源码看,它内部维护 mVersion 代表数据版本号,每次数据更新 mVersion 递增,ObserverWrapper 中的 mLastVersion 记录观察者最后接收数据版本号。新观察者注册时,若 mLastVersion 小于 mVersion,就会接收数据,导致数据倒灌。
    • 解决方案
      • SingleLiveEvent:它通过 AtomicBoolean 类型的 mPending 标志位控制数据消费。数据更新时,mPending 设为 true,观察者接收数据后设为 false,保证数据只被消费一次。从其源码实现可知,在 observe 方法中判断 mPending 状态决定是否通知观察者。
      • 自定义 LiveData 包装类:在自定义包装类中添加版本号或标记位。如在包装类中维护一个 AtomicInteger 类型的版本号,每次数据更新时版本号递增,在 observe 方法中,观察者接收数据后记录当前版本号,下次数据更新时对比版本号,若相同则不通知,从而避免数据倒灌。

ViewModel 对 UI 数据管理的源码级别分析

数据存储与生命周期管理

ViewModel 的生命周期由 ViewModelStore 和 ViewModelProvider 管理。ViewModelProvider 负责创建和获取 ViewModel 实例,它会先从 ViewModelStore 中查找是否存在该 ViewModel 实例,如果存在则直接返回,不存在则创建新的实例。

// ViewModelProvider 关键代码
public class ViewModelProvider {private final Factory mFactory;private final ViewModelStore mViewModelStore;public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {mFactory = factory;mViewModelStore = store;}@NonNull@MainThreadpublic <T extends ViewModel> T get(@NonNull Class<T> modelClass) {String canonicalName = modelClass.getCanonicalName();if (canonicalName == null) {throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");}return get(DEFAULT_KEY + ":" + canonicalName, modelClass);}@NonNull@MainThreadpublic <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {ViewModel viewModel = mViewModelStore.get(key);if (modelClass.isInstance(viewModel)) {//noinspection uncheckedreturn (T) viewModel;} else {//noinspection StatementWithEmptyBodyif (viewModel != null) {// TODO: log a warning.}}viewModel = mFactory.create(modelClass);mViewModelStore.put(key, viewModel);//noinspection uncheckedreturn (T) viewModel;}
}

这样,在配置变更时,ViewModel 实例不会被销毁,保证了数据的存储。

数据更新与通知

ViewModel 通常使用 LiveData 来存储和通知 UI 数据的变化。当 ViewModel 中的数据更新时,调用 LiveData 的 setValue 或 postValue 方法,LiveData 会遍历所有观察者并调用其 onChanged 方法。

// LiveData 关键代码
private void considerNotify(ObserverWrapper observer) {if (!observer.mActive) {return;}if (!observer.shouldBeActive()) {observer.activeStateChanged(false);return;}if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;//noinspection uncheckedobserver.mObserver.onChanged((T) mData);
}

通过这种方式,ViewModel 实现了对 UI 数据的管理和更新通知。

面试扩展:

  1. 从源码角度分析 ViewModel 如何确保在配置变更时 UI 数据不丢失,以及如何与 LiveData 协作更新 UI。
    回答
    • 配置变更时数据不丢失ViewModel 借助 ViewModelStore 和 ViewModelProvider 实现。ViewModelStore 内部用 HashMap 存储 ViewModel 实例,ViewModelProvider 在创建或获取 ViewModel 实例时,先从 ViewModelStore 查找,若存在则返回,不存在才创建新实例。例如在屏幕旋转等配置变更时,ViewModel 实例得以保留,确保 UI 数据不丢失。
    • 与 LiveData 协作更新 UIViewModel 通常使用 LiveData 存储和通知 UI 数据变化。当 ViewModel 中数据更新,调用 LiveData 的 setValue 或 postValue 方法,LiveData 会遍历观察者调用 considerNotify 方法,在 considerNotify 方法中判断观察者状态和版本号等条件后,调用观察者的 onChanged 方法通知 UI 更新。

相关文章:

kotlin和MVVM的结合使用总结(二)

MVVM 架构详解 核心组件&#xff1a;ViewModel 和 LiveData 在 Android 中&#xff0c;MVVM 架构主要借助 ViewModel 和 LiveData 来实现。ViewModel 负责处理业务逻辑&#xff0c;而 LiveData 则用于实现数据的响应式更新。 ViewModel 的源码分析 ViewModel 的核心逻辑在 …...

U盘能识别但无法写入数据的原因

1. U 盘物理损坏 原因&#xff1a;U 盘内部存储芯片、电路板或接口接触不良&#xff0c;可能因摔落、高温、频繁插拔等导致。表现&#xff1a;插入电脑能识别盘符&#xff0c;但读写时提示 “磁盘错误”“无法访问” 或操作无反应。解决方法&#xff1a; 尝试用其他设备&#…...

多模态大模型 Qwen2.5-VL 的学习之旅

Qwen-VL 是阿里云研发的大规模视觉语言模型&#xff08;Large Vision Language Model, LVLM&#xff09;。Qwen-VL 可以以图像、文本、检测框作为输入&#xff0c;并以文本和检测框作为输出。Qwen-VL 系列模型性能强大&#xff0c;具备多语言对话、多图交错对话等能力&#xff…...

linux sudo 命令介绍

sudo&#xff08;superuser do&#xff09;是一个用于 Linux 系统的命令&#xff0c;它允许授权用户以其他用户&#xff08;通常是 root 超级用户&#xff09;的安全权限执行命令。 有了 sudo&#xff0c;用户在执行特定的、需要更高权限的操作时&#xff0c;就不需要切换到 r…...

STM32F103系列单片机寄存器操作和标准库操作

关于stm32&#xff0c;标准库很早就学完了&#xff0c;但如果想要更加深入学习计算机硬件&#xff0c;那么学会寄存器操作是非常有必要的。今天从最简单的点灯开始&#xff0c;我们来对比一下二者的不同。 一、寄存器操作和标准库操作中点亮LED的区别 寄存器操作&#xff1a;…...

如何解决PyQt从主窗口打开新窗口时出现闪退的问题

在PyQt5中&#xff0c;当从主窗口打开新窗口时&#xff0c;经常会出现闪退现象&#xff0c;这通常是由于对象生命周期管理不当或事件循环错误等所导致。 1. 确保新窗口实例被正确引用 新窗口的实例若未被主窗口引用&#xff0c;可能会被Python的垃圾回收机制销毁。 错误示例&…...

2025五一杯数学建模竞赛思路助攻预定

2025五一杯数学建模竞赛思路助攻预定&#xff08;思路内容见文末名片&#xff09; 一、概况 数学建模竞赛是一项模拟面对实际问题寻求解决方案的活动&#xff0c;是一次近似 于“真刀真枪”的创新探索性实践训练。在丰富并活跃学生课外生活活动的同 时&#xff0c;数学建模竞…...

Java集合框架解析

一、集合框架概述 1. 集合框架体系结构 Java集合框架&#xff08;Java Collections Framework, JCF&#xff09;位于java.util包中&#xff0c;包含三大核心接口&#xff1a; Collection&#xff1a;单列数据集合的根接口 List&#xff1a;有序可重复集合Set&#xff1a;无序…...

《100天精通Python——基础篇 2025 第1天:从编程语言到计算机基础,开启你的学习之旅》

目录 一、计算机组成原理之概述篇二、编程语言是什么三、编译型语言和解释型语言的区别3.1 编译型语言3.2 解释型语言 四、Python是什么五、Python有哪些优点和缺点&#xff1f;5.1 Python的优点5.2 Python 的缺点 六、学Python能干什么&#xff0c;Python的应用领域有哪些&…...

JavaFX 第三篇 HostServices和Platform

1、HostServices类 介绍这个类主要是使用里面的一个方法 返回类型方法说明voidshowDocument(java.lang.String uri)使用默认浏览器打开一个url地址 /*** description: 程序打开3秒后&#xff0c;打开百度* author: HK* since: 2025/4/24 16:40*/ public class Demo1 extends…...

【Java 8新特性】Stream API 和 Lambda 表达式

一、前言 Java 8 的 Stream API 和 Lambda 表达式 为集合处理带来了函数式编程风格&#xff0c;显著简化了代码并提高了可读性。 二、Lambda 表达式 1.作用 简化匿名内部类的语法&#xff0c;允许将函数作为参数传递。实现函数式接口&#xff08;只有一个抽象方法的接口&…...

Vue 3 相比 Vue 2 的优势

1. 性能优化 更快的渲染&#xff1a; 基于 Proxy 的响应式系统&#xff0c;比 Vue 2 的 Object.defineProperty 更高效&#xff0c;初始化速度和内存占用优化显著。编译时优化&#xff08;如静态树提升、补丁标志等&#xff09;&#xff0c;减少运行时开销。 更小的体积&#…...

深度解析 TransmittableThreadLocal(TTL):原理、实战与优化指南

深度解析 TransmittableThreadLocal(TTL):原理、实战与优化指南 在现代 Java 应用中,ThreadLocal 被广泛用于线程隔离上下文,比如用户会话、链路追踪等。但随着线程池的普及,ThreadLocal 也暴露出严重局限性,尤其是在异步场景中上下文无法正确传递的问题。 本文从 Thr…...

入门 Go 语言

本专栏的 Go 语言学习参考了B站UP 软件工艺师的视频 本节需要&#xff1a; Go 语言环境VSCode 安装环境 下载 Go 环境&#xff0c;并安装下载 VSCode&#xff0c;安装。在 VSCode 中安装 Go 扩展&#xff1a; 接下来就可以编写 Go 语言了 第一条 Go Go 语言是一种编译型…...

膳食营养诊断活动:科技赋能,共筑全民健康新基石

膳食营养诊断活动&#xff1a;科技赋能&#xff0c;共筑全民健康新基石 一、活动背景&#xff1a;响应营养周号召&#xff0c;开启健康新征程 &#xff08;一&#xff09;2025营养周主题解读 2025年全民营养周的核心主题“吃动平衡&#xff0c;健康体重&#xff0c;全民行动…...

考拉悠然:科技与匠心,以烟草虫情AI监测系统共筑品质未来

李工&#xff0c;一位在卷烟厂辛勤耕耘了二十余载的老工艺师&#xff0c;他的青春和汗水&#xff0c;都挥洒在了这片弥漫着烟草香气的土地上。他像一位老农&#xff0c;精心呵护着每一片烟叶&#xff0c;因为他深知&#xff0c;烟草品质的把控&#xff0c;就是守护着卷烟厂的生…...

k8s基于角色的访问控制(RBAC)

Kubernetes&#xff08;k8s&#xff09;权限管理主要是基于角色的访问控制&#xff08;RBAC&#xff09;&#xff0c;以下是其核心内容&#xff1a; 核心概念 Role 和 ClusterRole Role &#xff1a;定义特定命名空间内的权限规则&#xff0c;用于在某个命名空间内设置访问权限…...

拆解华为Pura X新发现:“仿生”散热与钛合金“骨架”

拆解华为Pura X新发现&#xff1a;“仿生”散热与钛合金“骨架” 原创 黑毛警长008 AR圈 2025年04月24日 09:42 广东 01 引言&#xff1a;AI时代带来折叠屏新挑战 随着华为Pura X的发布&#xff0c;市场上已出现多家机构的拆解分析&#xff0c;但大多聚焦于芯片和电子组件层面…...

Typecho 访客统计插件最新版-前后台统计图均可显示

这是一个为 Typecho 博客系统开发的访客统计插件&#xff0c;基于原版的VistorLogger修改版本。该插件提供了详细的访问统计功能&#xff0c;包括访问国家/地区统计、IP分布等信息&#xff0c;并进行了隐私保护处理。 功能特点 独立页面模板显示访问国家/地区统计&#xff08…...

与智者同行:京东零售技术人的成长书单

我们正处在一个快速变化的时代&#xff0c;信息洪流奔涌而来&#xff0c;如何穿透纷繁的表象&#xff0c;理解世界的复杂性&#xff1f;又如何在充满不确定性的环境中&#xff0c;找到属于自己的方向&#xff1f; 阅读&#xff0c;是最从容的答案&#xff0c;让我们站在智者的…...

matplotlib1-画成对数据图

画图的类型 成对数据&#xff08;Pairwise data&#xff09; 成对形式的数据 (x, y)&#xff1b;表格形式的数据 (var_0, var_1, ..., var_n) &#xff1b;函数形式的数据 f(x) y 1. 绘图-plot(x, y) 以线条或标记的形式将 y 随 x 的变化情况绘制成图表。 2. 散点图-scatt…...

深入理解表单---提交用户与网页交互的重要方式:GET 与 POST 的本质区别与应用实践

在 Web 开发中&#xff0c;表单&#xff08;<form>&#xff09;是用户与网页交互的重要方式&#xff0c;而表单的 method 属性则决定了数据是如何发送到服务器的。本文将带你系统理解 GET 和 POST 请求方式的区别、使用场景与注意事项&#xff0c;并结合示例进行实战分析…...

VIVADO中单bit信号的跨时钟域处理(快时钟到慢时钟)

VIVADO中单bit信号的跨时钟域处理 同步触发器的约束&#xff0c;确保软件布局布线时把同步的触发器放到同一个SLICE中 目录 前言 一、快时钟的脉冲到慢时钟的同步方法一 1、正确结果 2、源时钟脉冲展宽组合逻辑输出不加触发器的风险 3、目的时钟采样组合逻辑输出不加触发器…...

解决 Windows10 下 UWP 应用无法使用本地代理

从Micorsoft Store下载的应用默认不允许使用本地代理(或者说就不允许访问localhost) 但是可以借助于系统自带的 CheckNetIsolation 工具来突破该限制 操作 找出要修改的应用 SID 在注册表 HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\Cur…...

实验三 进程间通信实验

一、实验目的 1、了解什么是信号。 2、熟悉LINUX系统中进程之间软中断通信的基本原理。 3、理解进程的同步关系。 4、掌握用信号实现进程间的同步操作。 5、了解什么是管道。 6、熟悉UNIX/LINUX支持的管道通信方式。 二、实验内容 1、阅读下列程序&#xff0c;执行程序…...

NHANES指标推荐:TyG-WHtR

文章题目&#xff1a;Can cardiovascular health and its modifiable healthy lifestyle offset the increased risk of all-cause and cardiovascular deaths associated with insulin resistance? DOI&#xff1a;10.1186/s12933-025-02674-z 中文标题&#xff1a;心血管健康…...

Winddows11官网下载安装VMware Workstation Pro17(图文详解)

Winddows11安装VMware17 1、官网下载2、安装3、总结 1、官网下载 官网地址 点击Products&#xff0c;滑到最下面&#xff0c;选择SEE DESKTOPP HYPERVISORS 选择 DOWNLOAD FUSION OR WORKSTATION 自动跳转到下面哪个服界面&#xff0c;注册 输入邮箱地址和图片下面的文字…...

YOLO训练时到底需不需要使用权重

1. 预训练权重的作用与本质 预训练权重&#xff08;Pretrained Weights&#xff09;是在大规模数据集上训练得到的模型参数。这些权重能够学习通用的特征模式&#xff0c;如边缘、纹理、形状等&#xff0c;从而帮助模型更快收敛并提高泛化能力。YOLO提供的官方预训练权重通常基…...

2025最新软件测试面试八股文(答案+文档+视频讲解)

1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前3年积累测试经验&#xff0c;按如何做好测试工程师的要点去要求自己&…...

SpringBoot整合AOP

没事做个Demo案例&#xff0c;首先看下项目结构&#xff1a; 第1步&#xff0c;导入依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency> 第2步…...

第16章:MCP服务端项目开发实战:对话系统

第16章:MCP服务端项目开发实战:对话系统 对话系统,尤其是聊天机器人和虚拟助手,是 AI Agent 最广泛的应用领域之一。然而,传统的对话系统常常面临挑战,如难以维持长对话连贯性、缺乏个性化交互、无法有效利用对话中积累的知识等。MCP(Memory, Context, Planning)框架为…...

JavaScript 页面刷新:从传统到现代的全面解析

在 Web 开发中&#xff0c;"刷新"是一个基础但极其重要的功能。本文将全面探讨页面刷新的实现方式&#xff0c;从传统方法到现代最佳实践&#xff0c;深入解析每一种方案的原理和适用场景&#xff0c;并给出实用代码示例。 一、理解页面刷新的本质 在 Web 开发中&am…...

2025年Google Play审核策略全面解析

大家好&#xff0c;我是老妙&#xff0c;出海十余年的老司机&#xff0c;目前在死磕google play上架这一块。 目前来说&#xff0c;上架这一块不管是合规产品还是不合规产品&#xff0c;都建议使用有在架包的老号&#xff0c;更稳定&#xff0c;上架的审核时间更短&#xff0c…...

使用PHP对接印度尼西亚股票市场

在本篇文章中&#xff0c;我们将介绍如何使用PHP语言与StockTV API接口对接&#xff0c;获取并处理印度尼西亚&#xff08;Indonesia&#xff09;的股票市场数据。我们将以查询IPO信息和查看涨跌排行榜为例&#xff0c;展示具体的操作流程。 准备工作 首先&#xff0c;确保您…...

第54讲:总结与前沿展望——农业智能化的未来趋势与研究方向

目录 一、本板块内容回顾:人工智能助力农业的多元化应用 ✅ 精准农业与AI ✅ 农业金融与AI ✅ AI与农业政策 ✅ 农业物联网与AI 二、前沿趋势与研究方向:迈向智能、可持续农业的未来 1. AIGC(生成式AI)在农业中的应用 2. 数字孪生农业:虚拟与现实的无缝对接 3. A…...

Go语言中包导入下划线的作用解析

在Go语言的代码中&#xff0c;有时会看到类似以下的导入语句&#xff1a; import _ "github.com/mattn/go-sqlite3"这种以下划线_开头的导入方式&#xff0c;显得有些特别&#xff0c;尤其是对于新手来说&#xff0c;可能会感到困惑&#xff0c;为什么要这样写&…...

Linux学习笔记之动静态库

相信点进这篇帖子的你一定在动静态库的学习中遇到了很多问题。笔者由于曾经囫囵吞枣地学习库的相关知识&#xff0c;导致在实际应用中漏洞百出。所以写下这篇帖子&#xff0c;为大家解答一些疑惑&#xff0c;同时也加强自己的学习印象。 一、库的理解 什么是库&#xff1f;我…...

生成运算树

目录 题目题目描述示例输入输出算法标签: 二叉树, d f s dfs dfs, 模拟, *递归下降算法思路代码*后续 A C AC AC代码 题目 题目描述 在某种脚本语言里&#xff0c;有一个形如 x(api-xn)eps 的运算表达式&#xff0c;该表达式由以下元素构成&#xff1a; 操作数&#xff1a;…...

为什么要提出Null-text Inversion

在传统扩散模型的反转过程中&#xff08;如DDIM Inversion&#xff09;&#xff0c;文本提示&#xff08;Prompt&#xff09;确实不直接影响反转过程&#xff0c;但Null-text Inversion的优化动机源于反转-重建后的图像在后续编辑时对文本的依赖性。以下分步骤详细解释&#xf…...

centos离线安装ssh

一、在有网络的环境中准备RPM包 1.在一台与离线机器相同版本和架构的CentOS系统上&#xff0c;安装必要工具&#xff1a; sudo yum install -y yum-utils 2.创建目录存放RPM包&#xff1a; mkdir /tmp/ssh_rpms 3.下载SSH相关包及其依赖 yumdownloader --resolve --destd…...

数据库安装和升级和双主配置

备份和导入数据 ./mysqldump -u root -p123321 test > test.sql rsync -av test.sql root192.168.0.212:/usr/local/mysql/ ./mysql -uroot -p test < …/test.sql sudo tar -zxvf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz -C /usr/local/ sudo ln -sfn /usr/loca…...

React 的 useEffect 清理函数详解

React 的 useEffect 清理函数详解 useEffect 是 React 中用于处理副作用&#xff08;side effects&#xff09;的 Hook&#xff0c;清理函数&#xff08;Cleanup Function&#xff09;是 useEffect 中返回的一个函数&#xff0c;用于清理或撤销副作用。清理函数的主要目的是确…...

C++ Lambda 表达式

Lambda 表达式的完整语法如下&#xff1a; [capture](parameters) mutable -> return_type { body }[capture]&#xff08;捕获列表&#xff09;&#xff1a;指定外部变量如何被 Lambda 表达式捕获&#xff08;按值或按引用&#xff09;。 (parameters)&#xff08;参数列…...

MATLAB 中的图形绘制

一、线图 plot 函数用来创建x和y值的简单线图。 x 0 : 0.05 : 30; %从0到30&#xff0c;每隔0.05取一次值 y sin(x); plot(x,y,LineWidth,2) %若&#xff08;x&#xff0c;y&#xff0c;LineWidth&#xff0c;2&#xff09;可变粗 xlabel("横轴标题") ylab…...

深度解析 Kubernetes 配置管理:如何安全使用 ConfigMap 和 Secret

目录 深度解析 Kubernetes 配置管理&#xff1a;如何安全使用 ConfigMap 和 Secret一、目录结构二、ConfigMap 和 Secret 的创建1. 创建 ConfigMapconfig/app-config.yaml&#xff1a;config/db-config.yaml&#xff1a; 2. 创建 Secretsecrets/db-credentials.yaml&#xff1a…...

【UVM项目实战】异步fifo—uvm项目结构以及uvm环境搭建

本文章同步到我的个人博客网站&#xff1a;ElemenX-King&#xff1a;【UVM项目实战】异步fifo—uvm项目结构以及uvm环境搭建 希望大家能使用此网站来进行浏览效果更佳&#xff01;&#xff01;&#xff01; 目录 一、异步FIFO1.1 异步FIFO的定义1.2 亚稳态1.3 异步FIFO关键技术…...

【含文档+PPT+源码】基于SpringBoot+Vue的移动台账管理系统

项目介绍 本课程演示的是一款 基于SpringBootVue的移动台账管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 3.该…...

C语言——函数

C语言——函数 函数的概念 函数&#xff1a;也叫子程序。C语言中的函数就是一个完成某项特定任务的一小段代码。C语言函数分类&#xff1a; 按照用户使用&#xff1a;库函数&#xff0c;自定义函数 按照参数的形式&#xff1a;无参函数&#xff0c;有参函数 按照是否有返回值…...

网络安全 | F5 WAF 黑白名单配置实践指南

关注&#xff1a;CodingTechWork 引言 在现代网络安全架构中&#xff0c;F5 Web Application Firewall (WAF) 是保护 Web 应用免受攻击的重要工具。F5 WAF 提供了强大的黑白名单功能&#xff0c;结合 Data Group 和 iRules&#xff0c;可以实现更灵活、更高效的流量控制策略。…...

黑马 redis面试篇笔记

redis主从 version: "3.2"services:r1:image: rediscontainer_name: r1network_mode: "host"entrypoint: ["redis-server", "--port", "7001"]r2:image: rediscontainer_name: r2network_mode: "host"entrypoint:…...