Android LiveData学习总结(源码级理解)
LiveData 工作原理
- 数据持有与观察者管理:
LiveData
内部维护着一个数据对象和一个观察者列表。当调用observe
方法注册观察者时,会将LifecycleOwner
和Observer
包装成LifecycleBoundObserver
对象并添加到观察者列表中。 - 生命周期感知:
LifecycleBoundObserver
实现了LifecycleEventObserver
接口,能够监听LifecycleOwner
的生命周期变化。当LifecycleOwner
进入活跃状态(STARTED
或RESUMED
)时,LiveData
会将最新数据发送给该观察者;当LifecycleOwner
进入销毁状态(DESTROYED
)时,LiveData
会自动移除该观察者,避免内存泄漏。 - 数据更新通知:当调用
setValue
(主线程)或postValue
(子线程)方法更新数据时,LiveData
会检查所有观察者的生命周期状态,只有处于活跃状态的观察者才会收到onChanged
方法的调用,从而更新 UI。
整体架构与核心类
LiveData
相关的核心类主要有 LiveData
、Observer
、LifecycleOwner
和 Lifecycle
。
LiveData
:数据持有者类,负责存储数据并通知观察者数据的变化。Observer
:观察者接口,定义了数据变化时的回调方法。LifecycleOwner
:具有生命周期的组件,如Activity
、Fragment
,实现了该接口。Lifecycle
:用于跟踪组件的生命周期状态。
工作流程与源码解析
1. 创建 LiveData
对象
LiveData<String> liveData = new MutableLiveData<>();
MutableLiveData
是 LiveData
的子类,它提供了 setValue()
和 postValue()
方法来更新数据。
2. 注册观察者
liveData.observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {// 数据变化时的回调}
});
下面是 observe()
方法的源码:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {assertMainThread("observe");if (owner.getLifecycle().getCurrentState() == DESTROYED) {// 如果 LifecycleOwner 已经销毁,直接返回return;}LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);if (existing != null && !existing.isAttachedTo(owner)) {throw new IllegalArgumentException("Cannot add the same observer"+ " with different lifecycles");}if (existing != null) {return;}owner.getLifecycle().addObserver(wrapper);
}
observe()
方法首先检查是否在主线程中调用,然后检查LifecycleOwner
的状态,如果已经销毁则直接返回。- 创建
LifecycleBoundObserver
对象,它是ObserverWrapper
的子类,实现了LifecycleEventObserver
接口,用于监听LifecycleOwner
的生命周期变化。 - 将
observer
和LifecycleBoundObserver
包装对象存入mObservers
集合中。 - 最后将
LifecycleBoundObserver
注册到LifecycleOwner
的生命周期观察者列表中。
3. 更新数据
可以使用 setValue()
或 postValue()
方法更新 LiveData
中的数据。
// 在主线程中更新数据
((MutableLiveData<String>) liveData).setValue("new value");// 在子线程中更新数据
((MutableLiveData<String>) liveData).postValue("new value");
setValue()
方法的源码:
@MainThread
protected void setValue(T value) {assertMainThread("setValue");mVersion++;mData = value;dispatchingValue(null);
}
setValue()
方法首先检查是否在主线程中调用,然后更新数据的版本号和数据值。- 调用
dispatchingValue()
方法通知所有观察者数据发生了变化。
postValue()
方法的源码:
protected void postValue(T value) {boolean postTask;synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;}if (!postTask) {return;}ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
postValue()
方法用于在子线程中更新数据,它会将数据存入mPendingData
中,并通过ArchTaskExecutor
将更新操作切换到主线程中执行。
4. 通知观察者
dispatchingValue()
方法用于通知观察者数据发生了变化:
void dispatchingValue(@Nullable ObserverWrapper initiator) {if (mDispatchingValue) {mDispatchInvalidated = true;return;}mDispatchingValue = true;do {mDispatchInvalidated = false;if (initiator != null) {considerNotify(initiator);initiator = null;} else {for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {considerNotify(iterator.next().getValue());if (mDispatchInvalidated) {break;}}}} while (mDispatchInvalidated);mDispatchingValue = false;
}
dispatchingValue()
方法会遍历所有的观察者,并调用considerNotify()
方法通知每个观察者。
considerNotify()
方法的源码:
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 unchecked((Observer<T>) observer.mObserver).onChanged((T) mData);
}
considerNotify()
方法会检查观察者的活跃状态和数据版本号,如果观察者不活跃或数据版本号没有变化,则不进行通知。- 如果满足条件,则调用观察者的
onChanged()
方法,将最新的数据传递给观察者。
扩展追问
LiveData
的 postValue
方法用于在后台线程中更新 LiveData
的值。不过,使用这个方法时可能会出现值丢失的情况,下面结合源码深入分析其原因。
postValue
方法源码分析
postValue
方法的实现位于 LiveData
类中,以下是 postValue
方法的源码:
protected void postValue(T value) {boolean postTask;synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;}if (!postTask) {return;}ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}private final Runnable mPostValueRunnable = new Runnable() {@Overridepublic void run() {Object newValue;synchronized (mDataLock) {newValue = mPendingData;mPendingData = NOT_SET;}setValue((T) newValue);}
};
值可能丢失的原因
1. 多线程并发调用 postValue
postValue
方法会将新值存储在 mPendingData
中,并通过 ArchTaskExecutor
将一个 Runnable
任务(mPostValueRunnable
)发送到主线程执行。当在多线程环境下频繁调用 postValue
方法时,可能会出现值丢失的情况。
具体来说,postValue
方法中有一个同步块:
synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;
}
在这个同步块中,会判断 mPendingData
是否为 NOT_SET
(表示没有待处理的值)。如果不是 NOT_SET
,则 postTask
为 false
,不会再次发送 Runnable
任务到主线程。这意味着,如果在 Runnable
任务还未执行时,又有新的 postValue
调用,新的值会覆盖 mPendingData
中的旧值,而旧值就会丢失。
例如,假设在后台线程中有两个线程同时调用 postValue
方法:
// 线程 1
liveData.postValue("value1");
// 线程 2
liveData.postValue("value2");
如果线程 2 在 mPostValueRunnable
还未执行时就调用了 postValue
方法,那么 mPendingData
中的值会从 "value1"
被覆盖为 "value2"
,最终 mPostValueRunnable
执行时,setValue
方法只会将 "value2"
发送给观察者,"value1"
就丢失了。
2. 主线程任务队列的延迟
postValue
方法会将 mPostValueRunnable
任务发送到主线程执行,而主线程有自己的任务队列。如果主线程比较繁忙,mPostValueRunnable
任务可能会延迟执行。在这个延迟期间,如果有新的 postValue
调用,同样会导致值丢失。
例如,当主线程正在处理大量的 UI 绘制任务时,mPostValueRunnable
任务可能会被阻塞在队列中。此时,如果有新的 postValue
调用,mPendingData
中的值会被更新,旧的值就会丢失。
解决方案
如果需要确保每个值都能被处理,可以使用 setValue
方法,但 setValue
方法必须在主线程中调用。如果需要在后台线程中更新值,可以考虑使用 MutableLiveData
的子类,自定义实现更新逻辑,确保每个值都能被正确处理。
// 在主线程中使用 setValue 方法更新值
liveData.setValue("newValue");
综上所述,LiveData
的 postValue
方法由于多线程并发调用和主线程任务队列的延迟,可能会导致值丢失。在使用时需要根据具体情况选择合适的更新方法。
总结
LiveData
的工作原理主要基于观察者模式和生命周期感知机制。
通过 observe()
方法注册观察者,将观察者与 LifecycleOwner
关联起来,当 LifecycleOwner
的生命周期状态发生变化时,LiveData
会自动处理观察者的活跃状态。
当数据更新时,LiveData
会通知所有活跃的观察者,确保只有在组件处于活跃状态时才更新 UI。这种设计使得 LiveData
具有良好的内存管理和用户体验。
相关文章:
Android LiveData学习总结(源码级理解)
LiveData 工作原理 数据持有与观察者管理:LiveData 内部维护着一个数据对象和一个观察者列表。当调用 observe 方法注册观察者时,会将 LifecycleOwner 和 Observer 包装成 LifecycleBoundObserver 对象并添加到观察者列表中。生命周期感知:L…...
RabbitMQ 为什么引入 Exchange 的概念, 交换机有什么作用.
RabbitMQ 引入 Exchange 的概念是为了实现消息的灵活路由和解耦生产者与消费者,这是 AMQP(Advanced Message Queuing Protocol)协议的核心设计之一。以下是 Exchange 存在的主要原因: 1. 解耦生产者与队列 问题:如果生…...
rabbitmq引入C++详细步骤
1. 安装RabbitMQ服务器 在Windows上:先安装Erlang,再安装RabbitMQ服务器。安装完成后,可通过访问http://localhost:15672来检查RabbitMQ服务器是否正常运行,默认的用户名和密码是guest/guest。 在Linux上:可使用包管理…...
Android 9.0系统源码定制:实现开机启动特定App的全面指南
在Android 9.0系统中,若需要通过修改系统源码实现开机启动特定应用(如系统预装应用或第三方应用),通常涉及对系统框架层(Framework)的深度定制开发。以下是详细的实现步骤和关键代码位置整理: 1…...
如何在不同版本的 Elasticsearch 之间以及集群之间迁移数据
作者:来自 Elastic Kofi Bartlett 当你想要升级一个 Elasticsearch 集群时,有时候创建一个新的独立集群并将数据从旧集群迁移到新集群会更容易一些。这让用户能够在不冒任何停机或数据丢失风险的情况下,在新集群上使用所有应用程序测试其所有…...
MySQL数据库精研之旅第六期:玩转数据库约束
目录 一、数据库约束的概念 二、约束类型 三、NOT NULL 非空约束 四、DEFAULT 默认值约束 五、UNIQUE 唯一约束 六、PRIMARY KEY 主键约束 七、FOREIGN KEY 外键约束 八、Check 约束 一、数据库约束的概念 数据库约束是指对数据库表中的数据所施加的规则或条件…...
【Java】面向对象程序三板斧——如何优雅设计包、封装数据与优化代码块?
🎁个人主页:User_芊芊君子 🎉欢迎大家点赞👍评论📝收藏⭐文章 🔍系列专栏:【Java】内容概括 【前言】 在Java编程中,类和对象是面向对象编程的核心概念。而包(Package&am…...
MCP、RAG与Agent:下一代智能系统的协同架构设计
一、智能系统架构的范式转移 1.1 传统架构的局限性 架构类型典型问题新架构需求单体架构扩展性差,维护成本高模块化解耦简单微服务缺乏智能决策能力认知能力嵌入纯LLM系统事实性错误,知识固化动态知识增强 1.2 三大核心组件的定位 #mermaid-svg-6tGuE…...
软件设计师2009-2022历年真题与答案解析(附pdf下载)
软考在即,现在给大家分享一下软件设计师2009-2022真题与答案解析 pdf全套,文末提供大家免费下载,大家都知道在软考备考过程中,拥有一套全面且实用的考试资料对于考生来说至关重要。目录如下: 历年真题及详解2004-2019 …...
前端 React 弹窗式 滑动验证码实现
目录 一、安装依赖 1、rc-slider-captcha 2、create-puzzle 二、个人封装好的组件拿去用 三、效果展示 一、安装依赖 这里需要引入两个依赖,若有后端图片接入,可以不引入第二个依赖 1、rc-slider-captcha 滑动验证码生成的库 国内网:…...
【触想智能】工业触摸一体机在金融智能设备领域上应用的优势
工业触摸一体机在金融智能设备领域上具有许多独特的优势。这些设备结合了工业级的强度和耐用性,以及先进的触控技术和高性能处理能力,为金融机构提供全面可靠的解决方案。下面将介绍工业触摸一体机在金融智能设备领域上的应用优势。 触想嵌入式工业触摸一…...
本地实现Rtsp视频流推送
简言:使用ffmpeg实现本地视频流推送 srs存储(延时推送) 准备工作 安装包: ffmpeg:http://ffmpeg.org/download.html EasyDarwin:EasyDarwin流媒体音视频资源汇总 srs安装教程地址:http://…...
人工智能中的卷积神经网络(CNN)综述
文章目录 前言 1. CNN的基本原理 1.1 卷积层 1.2 池化层 1.3 全连接层 2. CNN的发展历程 2.1 LeNet-5 2.2 AlexNet 2.3 VGGNet 2.4 ResNet 3. CNN的主要应用 3.1 图像分类 3.2 目标检测 3.3 语义分割 3.4 自然语言处理 4. 未来研究方向 4.1 模型压缩与加速 4.2 自监督学习 4.3 …...
Mac电脑交叉编译iphone设备可以运行的redsocks, openssl, libsevent
准备:intel x86_64芯片的mac电脑,系统为mac os15.3.1,iphone为6s的ios14.4(rootful越狱) 第一步:准备工具链(推荐使用 theos clang) 如果你已经安装过 Theos(或 NewTheos)&#x…...
入门51单片机(1)-----点灯大师梦开始的地方
前言 这一次的博客主要是要记录一下学习的记录的,方便以后去复习一下的,当然这篇博客还是针于零基础的伙伴萌,看完这篇博客,大家就可以学会点灯了。 安装软件 方法一下一下来教!!萌新宝贝萌可以学会的!帮…...
[1-01-09].第08节:基础语法 - 数组常见算法 + Arrays工具类 + 数组中常见异常
一、 数组的常见算法 1.1 数值型数组特征值统计 这里的特征值涉及到:平均值、最大值、最小值、总和等 **举例1:**数组统计:求总和、均值 public class TestArrayElementSum {public static void main(String[] args) {int[] arr {4,5,6,…...
dnf install openssl失败的原因和解决办法
网上有很多编译OpenSSL源码(3.x版本)为RPM包的文章,这些文章在安装RPM包时都是执行rpm -ivh openssl-xxx.rpm --nodeps --force 这个命令能在缺少依赖包的情况下能强行执行安装 其实根据Centos的文档,安装RPM包一般是执行yum install或dnf install。后者…...
UE5 Chaos :官方文献总结 + 渲染网格体 (Render Mesh) 和模拟网格体 是如何关联的?为什么模拟网格体 可以驱动渲染网格体?
官方文献:https://dev.epicgames.com/community/learning/tutorials/pv7x/unreal-engine-panel-cloth-editor 1. 流程概述 本文档介绍了如何通过面板编辑器(Panel Editor)在Unreal Engine中生成基于面板的布料资源。流程主要包含从Marvelou…...
Swift观察机制新突破:如何用AsyncSequence实现原子化数据监听?
网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...
Lombok库
文章目录 Lombok1.介绍2.主要注解2.1如何使用 Lombok2.1.1添加依赖2.1.2 使用Lombok注解2.1.3Lombok的其他常用注解ValueBuilderGoF23种设计模式之一:建造模式使用Builder注解自动生成建造模式的代码 SingularSlf4j使用选择合适的注解 Lombok 1.介绍 Lombok 是一个…...
算法思想之模拟
欢迎拜访:雾里看山-CSDN博客 本篇主题:算法思想之模拟 发布时间:2025.4.14 隶属专栏:算法 目录 滑动窗口算法介绍核心特点常见问题优化方向 例题替换所有的问号题目链接题目描述算法思路代码实现 提莫攻击题目链接题目描述算法思路…...
Windows 系统如何使用Redis 服务
前言 在学习过程中,我们长期接触到的是Mysql 关系型数据库,也是够我们平时练习项目用的,但是后面肯定会有大型数据的访问就要借助新的新的工具。 一、什么是Redis Redis(Remote Dictionary Server)是一个基于内存的 键…...
2025年常见渗透测试面试题-红队面试宝典上(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 一、如何判断是否是域环境? 二、定位域控的 IP 三、定位域管所在机器 四、Kerberos 核心…...
Base64在线编码解码 - 加菲工具
Base64在线编码解码 - 加菲工具 打开网站 加菲工具 选择“Base64 在线编码解码” 或者直接打开https://www.orcc.top/tools/base64 输入需要编码/解码的内容,点击“编码”/“解码”按钮 编码: 解码: 复制已经编码/解码后的内容。...
前端面试宝典---闭包
闭包介绍 使用闭包: 在函数内声明一个变量,避免外部访问在该函数内再声明一个函数访问上述变量(闭包)返回函数内部的函数使用完毕建议闭包函数null;译放内存 function createCounter() {let count 0;return function () {coun…...
算法:有一个整数数组,长度为n。她希望通过一系列操作将数组变成一个回文数组。
小红有一个整数数组,长度为n。她希望通过一系列操作将数组变成一个回文数组。每次操作可以选择数组中任意两个相邻的元素 ai和 ai1,将它们的值同时加一。请你计算至少需要多少次操作使得数组变成一个回文数组。如果不可能,则输出-1。否则输出…...
数字人:开启医疗领域的智慧变革新时代(5/10)
摘要:数字人技术作为医疗变革的基石,通过多学科融合实现虚拟医生、手术模拟、医学教育等多元应用,贯穿诊前、术中、术后全流程,显著提升医疗效率、优化资源分配、推动个性化服务。尽管面临技术、伦理、数据安全等挑战,…...
正则表达式在线校验(RegExp) - 加菲工具
正则表达式在线校验 - 加菲工具 打开网站 加菲工具 选择“正则表达式在线校验” 或者直接打开https://www.orcc.top/tools/regexp 输入待校验的源文本与正则表达式,点击“校验”按钮 需要注意检验后的内容可能存在多空格,可以拉下去看看~...
某车企面试备忘
记录两个关于Binder的问题,我感觉面试官提的非常好,作一下备忘。 1.通过Binder进行的IPC(进程间通信)是线程阻塞的吗? 参考答案: Binder是Android平台的一种跨进程通信(IPC)机制&…...
从Ampere到Hopper:GPU架构演进对AI模型训练的颠覆性影响
一、GPU架构演进的底层逻辑 AI大模型训练效率的提升始终与GPU架构的迭代深度绑定。从Ampere到Hopper的演进路径中,英伟达通过张量核心升级、显存架构优化、计算范式革新三大技术路线,将LLM(大语言模型)训练效率提升至…...
【JavaEE】SpringBoot 统一功能处理
目录 一、拦截器1.1 使用1.1 定义拦截器1.2 注册配置拦截器 1.2 拦截器详解1.2.1 拦截路径1.2.2 拦截器执⾏流程 1.3 适配器模式 二、统一数据返回格式2.1 简单用法2.2 问题及解决 三、统一异常处理 一、拦截器 拦截器:拦截器是Spring框架提供的核⼼功能之⼀&#…...
杨辉三角(力扣 118)
118. 杨辉三角 - 力扣(LeetCode) 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2: 输入: numRows 1 输出: [[1]] vector<vector<int>> generate(int numRows) { //生成有numRows个元素(vector<in…...
三周年创作纪念日
文章目录 回顾与收获三年收获的五个维度未来的展望致谢与呼唤 亲爱的社区朋友们,大家好! 今天是 2025 年 4 月 14 日,距离我在 2022 年 4 月 14 日发布第一篇技术博客《SonarQube 部署》整整 1,095 天。在这条创作之路上,我既感慨…...
[c语言日记]轮转数组算法(力扣189)
【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…...
【Unity笔记】Unity超时检测器开发:支持自定义重试次数与事件触发
在Unity游戏或应用开发中,我们经常会遇到需要检测超时的场景,比如: 等待用户在限定时间内完成某个交互;等待网络请求或资源加载是否在规定时间内返回;控制AI角色等待某个事件发生,超时后执行备选逻辑。 在…...
【微服务管理】注册中心:分布式系统的基石
在分布式系统日益普及的当下,如何高效地管理众多服务实例成为关键问题。注册中心应运而生,它犹如分布式系统的 “指挥中枢”,承担着服务注册、发现等核心任务,为整个系统的稳定运行和高效协作提供坚实保障。本文将深入探讨注册中心…...
P10413 [蓝桥杯 2023 国 A] 圆上的连线
题意: 给定一个圆,圆上有 n2023 个点从 1 到 n 依次编号。 问有多少种不同的连线方式,使得完全没有连线相交。当两个方案连线的数量不同或任何一个点连接的点在另一个方案中编号不同时,两个方案视为不同。 答案可能很大&#x…...
计算机操作系统——存储器管理
系列文章目录 1.存储器的层次结构 2.程序的装入和链接 3.连续分配存储管理方式(内存够用) 4.对换(Swapping)(内存不够用) 5.分页存储管理方式 6.分段存储管理方式 文章目录 系列文章目录前言一、存储器的存储结构寄存器&…...
TCPIP详解 卷1协议 四 地址解析协议
4.1——地址解析协议(ARP) 对于TCP/IP网络,地址解析协议(ARP)[RFC0826]提供了一种在IPv4地址和各种网络技术使用的硬件地址之间的映射。ARP仅用于IPv4。IPv6使用邻居发现协议,它被合并入ICMPv6。当两个局域网的主机之间传输的以太…...
履带小车+六轴机械臂(2)
本次介绍原理图部分 开发板部分,电源供电部分,六路舵机,PS2手柄接收器,HC-05蓝牙模块,蜂鸣器,串口,TB6612电机驱动模块,LDO线性稳压电路,按键部分 1、开发板部分 需要注…...
耘想WinNAS:以聊天交互重构NAS生态,开启AI时代的存储革命
一、传统NAS的交互困境与范式瓶颈 在传统NAS(网络附加存储)领域,用户需通过复杂的图形界面或命令行工具完成文件管理、权限配置、数据检索等操作,学习成本高且效率低下。例如,用户若需搜索特定文件,需手动…...
如何通过自动化解决方案提升企业运营效率?
引言 在现代企业中,运营效率直接影响着企业的成本、速度与竞争力。尤其是随着科技的不断发展,传统手工操作和低效的流程逐渐无法满足企业的需求。自动化解决方案正成为企业提升运营效率、降低成本和提高生产力的关键。无论是大型跨国公司,还…...
【笔记ing】AI大模型-03深度学习基础理论
神经网络:A neural network is a network or circuit of neurons,or in a modern sense,an artificial neural network,composed of artificial neurons or nodes.神经网络是神经元的网络或回路,或者在现在意义上来说,是一个由人工神经元或节…...
Spring-注解编程
注解基础概念 1.什么是注解编程 指的是在类或者方法上加入特定的注解(XXX) 完成特定功能的开发 Component public classXXX{} 2.为什么要讲注解编程 1.注解开发方便 代码简洁 开发速度大大提高 2.Spring开发潮流 Spring2.x引入注解 Spring3.x完善注解 Springboot普及 推广注解…...
大数据学习栈记——MongoDB安装
本文介绍NoSQL技术:MongoDB的安装。操作系统:Ubuntu24.04 MongoDB介绍 MongoDB是一个基于分布式文件存储的数据库,由C语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系数据库和非关系数据库之…...
linux 系统编程基础部分 day1
常用指令 创建修改用户组 查看当前用户组:whoami 创建用户 sudo adduser 用户 sudo addgroup 组名 添加权限:chmod [u,g,o,a][x,w,r] 数字表示法r4 w2 x1 chmod 471 每个权限种类想加 给文件换所属用户 chown 新用户名 文件名 chgrp …...
访问不到服务器上启动的llamafactory-cli webui
采用SSH端口转发有效,在Windows上面进行访问 在服务器上启动 llamafactory-cli webui 后,访问方式需根据服务器类型和网络环境选择以下方案: 一、本地服务器(物理机/虚拟机) 1. 直接访问 若服务器与操作设备处于同一…...
论文阅读笔记——Generating Long Sequences with Sparse Transformers
Sparse Transformer 论文 解决了 Transformer 在长序列建模时的计算开销和内存过大的问题。 可视化了一个 128 层自注意力在 CIFAR-10 的数据集上学习到的注意力模式,发现:1)稀疏性普遍存在:大多数层在多数数据点上表现出稀疏注意…...
【信息系统项目管理师】高分论文:论信息系统项目的整合管理(旅游景区导游管理平台)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文一、制定项目章程二、制订项目管理计划三、指导和管理项目工作四、管理项目知识五、监控项目工作六、实施整体变更控制七、结束项目或阶段论文 在国家《中国旅游“十三五”发展规划信息化专项规划的背景下…...
C++ 用红黑树封装map/set
前言 一、源码结构分析 二、模拟实现map/set 2.1 套上KeyOfT 2.2 普通迭代器实现 2.3 const迭代器实现 2.4 解决key不能修改的问题 2.5 map的[]实现 2.6 map/set以及红黑树源码 2.6.1 RBTree.h 2.6.2 set.h 2.6.3 map.h 总结 前言 之前的文章讲解了红黑树的具体实…...