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

Moya 网络框架

Moya 网络框架

通过 Moya 进行网络请求的一般步骤如下:
1. 定义 TargetType:为每个 API 请求创建一个枚举,遵循 TargetType 协议,指定基础 URL、请求路径、方法、参数等。
2. 创建 MoyaProvider:实例化 MoyaProvider,并传入对应的 TargetType 枚举。
3. 发送请求:使用 MoyaProvider 发起请求并处理响应。
4. 解析数据:对响应数据进行解析(通常是 JSON 格式)。
5. 使用 RxSwift(可选):如果你需要响应式编程,可以将请求转换为 Observable,并使用 RxSwift 提供的操作符来处理异步数据流。
6. 处理错误:通过检查 MoyaError 来处理网络请求中的各种错误。

定义enum类型,有多种接口就定义多少种,然后实现TargetType协议

import Foundation
//导入网络框架
import Moyaenum DefaultService {//广告列表case ads(position : Int)case sheets(size:Int)case sheetDetail(data: String)case register(data : User)
}// MARK: - 实现TargetType协议
extension DefaultService:TargetType {//返回API地址var baseURL: URL {return URL(string: Config.ENDPOINT)!}//返回每个请求的路径var path: String {switch self {case.ads(_):return "v1/ads"case .sheets :return "v1/sheets"case .sheetDetail(let data):return "v1/sheets/\(data)"case .register(_) :return "v1/users"default:fatalError("error")}}//请求方式var method: Moya.Method {switch self {case .register :return .postdefault:return .get}}var task: Moya.Task {switch self {case .ads(let position):return ParamUtil.urlRequestParamters(["position":position])case .sheets(let size):return ParamUtil.urlRequestParamters(["size":size])default ://不传递任何参数return .requestPlain}}var headers: [String : String]? {var headers: Dictionary<String,String> = [:]return headers}}

使用方法

        let provider = MoyaProvider<DefaultService>()provider.request(.sheets(size: 10)) { result inprint(result)switch result {case let .success(response) :let data = response.datalet statusCode = response.statusCodelet datastring = String(data: data,encoding: .utf8)!print(statusCode)print(datastring)case let .failure(error) :print(error)}}

可以看到,最后返回的形式为字符串,不方便使用,所以需要进一步进行封装,将其转换为对象

使用RxSwift框架请求网络
//rxSwift 方式
provider.rx.request(.sheets(size: 10)).debug("Request").subscribe { event inswitch event {case let .success(response) :print("hello ")let data = response.datalet statusCode = response.statusCodelet datastring = String(data: data,encoding: .utf8)!print(statusCode)print(datastring)if let r = SheetListResponse.deserialize(from: datastring){print(r.status)print(r.data.data[0].title!)}case let .failure(error) :print(error)}}.disposed(by: rx.disposeBag) //释放相关资源,防止内存泄露
使用框架解析JSON数据

使用第三方库HandyJSON

根据给出的JSON格式,建立相关的类即可

然后把字符串转换成相对应的格式即可

if let r = SheetListResponse.deserialize(from: datastring)
封装自动解析JSON功能

对Observable进行拓展

// MARK: - 扩展Observable
extension Observable{/// 将字符串解析为对象////// - Parameter type: 要转为的类/// - Returns: 转换后的观察者对象public func mapObject<T:HandyJSON>(_ type:T.Type) -> Observable<T> {map { data in//将参数尝试转为字符串guard let dataString = data as? String else {//data不能转为字符串throw IxueaError.objectMapping}guard let result = type.deserialize(from: dataString) else{throw IxueaError.objectMapping}//解析成功//返回解析后的对象return result}}
}

在 Swift 中,map 是一种高阶函数,通常用于对集合(如数组、字典、可选值等)中的元素进行转换或映射。在你的代码中,map 用于将某个数据转换为期望的类型。

map 的基本作用:

map 会对序列中的每个元素执行一个闭包,然后返回一个新序列,其中每个元素都经过闭包的处理。

let numbers = [1, 2, 3]
let doubledNumbers = numbers.map { $0 * 2 }
// doubledNumbers == [2, 4, 6]

在这个例子中,map 会遍历 numbers 数组中的每个元素,并将每个元素乘以 2,然后返回一个新的数组。

代码中 map 的使用:

代码中使用 map 似乎是在处理一些数据转换,具体是将某种类型的数据(data)尝试转为字符串类型,并解析成目标类型对象。详细讲解如下:

map { data in// 将参数尝试转为字符串guard let dataString = data as? String else {// data 不能转为字符串throw IxueaError.objectMapping}guard let result = type.deserialize(from: dataString) else {throw IxueaError.objectMapping}// 解析成功// 返回解析后的对象return result
}

分解讲解:

​ 1. map { data in … }

​ • map 会对集合中的每个元素执行闭包中的代码,并返回一个新集合。这里的闭包是 data in { … },它接受集合中的每个元素作为输入(在这里是 data)。

​ • data 可能是一个原始数据,可以是任何类型,但在此代码中,它最终被尝试转换为 String 类型。

​ 2. guard let dataString = data as? String else { throw IxueaError.objectMapping }

​ • 使用 guard let 尝试将 data 转换为 String 类型。如果转换失败(即 data 不是一个字符串),则会跳转到 else 语句,抛出错误(IxueaError.objectMapping),中断当前的操作并退出。

​ • guard let 语句是一种早期退出的方式,用来简化条件判断并在条件不满足时处理错误。

​ 3. guard let result = type.deserialize(from: dataString) else { throw IxueaError.objectMapping }

​ • 假设 type 是一个类型,它提供了 deserialize(from:) 方法,用来将 dataString 字符串解析成目标类型的对象。

​ • 如果解析失败(即 deserialize 返回 nil),同样会抛出一个错误。deserialize 可能返回一个 nil,表示无法从字符串中成功解析出对象。

​ 4. return result

​ • 如果 data 成功转换为字符串,并且字符串成功被解析为目标类型的对象,最终的 result 会被返回。这个 result 就是经过 map 处理后得到的新元素。

总结:

​ • map:遍历集合中的每个元素,并应用闭包中的代码,返回转换后的新集合。

​ • guard:用于提前退出函数,如果条件不成立则抛出错误(throw IxueaError.objectMapping)。

​ • deserialize:将字符串解析成目标类型,如果失败则抛出错误。

代码的核心目的是将原始数据转换为字符串,然后再将字符串解析为目标类型对象。如果过程中有任何失败的地方(如类型转换失败或解析失败),都会抛出错误并停止处理。

对网络部分进行封装

为了解决JSON中相同类型对复用,所以将一些公共部分对类型写成一个类去继承,这样就避免了对于每一个JSON格式都需要再进行定义该类型。

同理,我们不可能对于每一个JSON去创建一个对应的类,所以使用范型,定义一些公共部分,每次传入该JSON应该属于什么类型即可。即定义了详情网络解析类,解析列表网络请求类

对Observable拓展moya网络相关功能
//
//  ObservableMoyaExtension.swift
//  对Observable拓展moya网络相关功能
//
//  Created by Unlimited_z on 2025/2/16.
//import Foundation
import HandyJSON
import Moya
import RxSwiftpublic enum IxueaError : Swift.Error {case objectMapping
}// MARK: - 扩展Observable
extension Observable{/// 将字符串解析为对象////// - Parameter type: 要转为的类/// - Returns: 转换后的观察者对象public func mapObject<T:HandyJSON>(_ type:T.Type) -> Observable<T> {map { data in//将参数尝试转为字符串guard let dataString = data as? String else {//data不能转为字符串throw IxueaError.objectMapping}guard let result = type.deserialize(from: dataString) else{throw IxueaError.objectMapping}//解析成功//返回解析后的对象return result}}
}//http网络请求观察者
public class HttpObserver<Element>:ObserverType{/// ObserverType协议中用到了泛型E/// 所以说子类中就要指定E这个泛型/// 不然就会报错public typealias E = Elementpublic typealias successCallback = ((E)-> Void)/// 请求成功回调var success:successCallback/// 请求失败回调var error:((BaseResponse?,Error?)-> Bool)?var controller:BaseLogicController?/// 构造方法////// - Parameters:///   - onSuccess: 请求成功的回调///   - onError: 请求失败的回调init(_ success:@escaping successCallback,_ error: ((BaseResponse?,Error?)-> Bool)?) {self.success = successself.error = error}/// 当RxSwift框架里面发送了事件回调////// - Parameter event: <#event description#>public func on(_ event: Event<Element>) {switch event {case .next(let data):
//            print("HttpObserver next \(data)")//将值尝试转为BaseResponselet baseResponse = data as? BaseResponseif baseResponse?.status != 0 {//状态码不等于0//表示请求出错了handlerResponse(baseResponse:baseResponse)} else {//请求正常success(data)}case .error(let error)://请求失败
//            print("HttpObserver error:\(error)")handlerResponse(error:error)case .completed://请求完成
//            print("HttpObserver completed")break}}/// 尝试处理错误网络请求////// - Parameters:///   - baseResponse: 请求返回的对象///   - error: 错误信息func handlerResponse(baseResponse:BaseResponse?=nil,error:Error?=nil) {if self.error != nil && self.error!(baseResponse,error) {//回调失败block//返回true,父类不自动处理错误//子类需要关闭loading,当前也可以父类关闭//暴露给子类的原因是,有些场景会用到//例如:请求失败后,在调用一个接口,如果中途关闭了//用户能看到多次显示loading,体验没那么好} else {//自动处理错误ExceptionHandleUtil.handlerResponse(baseResponse,error)}}}// MARK: - 扩展ObservableType
// 目的是添加两个自定义监听方法
// 一个是只观察请求成功的方法
// 一个既可以观察请求成功也可以观察请求失败
extension ObservableType{/// 观察成功和失败事件////// - Parameter onSuccess: <#onSuccess description#>/// - Returns: <#return value description#>func subscribe(_ success:@escaping ((Element)-> Void),_ error: @escaping ((BaseResponse?,Error?)-> Bool)) -> Disposable {//创建一个Disposablelet disposable = Disposables.create()//创建一个HttpObserverlet observer = HttpObserver<Element>(success,error)//创建并返回一个Disposablesreturn Disposables.create(self.asObservable().subscribe(observer),disposable)}/// 观察成功的事件////// - Parameter onSuccess: <#onSuccess description#>/// - Returns: <#return value description#>func subscribeSuccess(_ controller:BaseLogicController?=nil, _ success:@escaping ((Element)-> Void) ) -> Disposable {let disposable = Disposables.create()let observer = HttpObserver<Element>(success,nil)return Disposables.create(self.asObservable().subscribe(observer),disposable)}
}

可以理解为,对第三方库的重写或是封装

这段代码的核心目的是将 Moya 网络请求的响应封装在 RxSwift 的 Observable 中,并提供更灵活的网络请求错误处理和数据绑定机制。

1. mapObject 扩展

public func mapObject<T:HandyJSON>(_ type:T.Type) -> Observable<T> {map { data inguard let dataString = data as? String else {throw IxueaError.objectMapping}guard let result = type.deserialize(from: dataString) else{throw IxueaError.objectMapping}return result}
}

作用:

​ • mapObject 是对 Observable 的扩展,用于将网络请求的结果(假设是 JSON 格式的字符串)转换为一个指定类型(如 User 或其他符合 HandyJSON 的对象)。

​ • 它会将原始的 data 转换为字符串,并通过 HandyJSON 库来解析为对象。

​ • 如果转换失败,会抛出 IxueaError.objectMapping 错误。

调用顺序:

​ 1. 你在 Observable 中调用 mapObject,传入目标类型 T。

​ 2. 通过 map 操作符对响应数据进行处理,把响应的 JSON 字符串解析为指定类型的对象。

2. HttpObserver 类

public class HttpObserver<Element>: ObserverType {public typealias E = Elementvar success: (E) -> Voidvar error: ((BaseResponse?, Error?) -> Bool)?public init(_ success: @escaping (E) -> Void, _ error: ((BaseResponse?, Error?) -> Bool)?) {self.success = successself.error = error}public func on(_ event: Event<Element>) {switch event {case .next(let data):let baseResponse = data as? BaseResponseif baseResponse?.status != 0 {handlerResponse(baseResponse: baseResponse)} else {success(data)}case .error(let error):handlerResponse(error: error)case .completed:break}}func handlerResponse(baseResponse: BaseResponse? = nil, error: Error? = nil) {if self.error != nil && self.error!(baseResponse, error) {// custom error handling} else {ExceptionHandleUtil.handlerResponse(baseResponse, error)}}
}

作用:

​ • HttpObserver 是 ObserverType 的实现,它处理 Observable 发出的事件。

​ • on 方法根据收到的事件类型(next、error、completed)来执行相应的处理:

​ • next:如果请求成功(状态码 status 为 0),则调用 success 回调;如果请求失败(状态码非 0),则调用 handlerResponse 处理错误。

​ • error:请求失败,调用 handlerResponse。

​ • completed:请求完成,什么都不做。

​ • handlerResponse 根据具体情况调用 ExceptionHandleUtil.handlerResponse 来处理错误。

调用顺序:

​ 1. HttpObserver 被用来观察 Observable 发送的事件(例如网络请求的结果)。

​ 2. 当 Observable 发出 next 事件时,HttpObserver 会检查响应的状态码并决定是否调用 success 回调或处理错误。

​ 3. 如果有错误,handlerResponse 会被调用,根据情况执行自定义的错误处理。

3. ObservableType 扩展

extension ObservableType {func subscribe(_ success: @escaping ((Element) -> Void), _ error: @escaping ((BaseResponse?, Error?) -> Bool)) -> Disposable {let disposable = Disposables.create()let observer = HttpObserver<Element>(success, error)return Disposables.create(self.asObservable().subscribe(observer), disposable)}func subscribeSuccess(_ success: @escaping ((Element) -> Void)) -> Disposable {let disposable = Disposables.create()let observer = HttpObserver<Element>(success, nil)return Disposables.create(self.asObservable().subscribe(observer), disposable)}
}

作用:

​ • 这里对 ObservableType 进行了扩展,添加了自定义的 subscribe 和 subscribeSuccess 方法:

​ • subscribe:这个方法接收成功和失败的回调,并将它们传给 HttpObserver 处理。

​ • subscribeSuccess:只关心请求成功的回调,不处理失败情况。这个方法的 error 参数为 nil。

调用顺序:

​ 1. 外部通过 subscribe 或 subscribeSuccess 方法订阅 Observable。

​ 2. 这些方法内部会创建一个 HttpObserver 并将它绑定到 Observable 上。

​ 3. 当 Observable 发出事件时(例如 next、error、completed),HttpObserver 会接收到这些事件并执行相应的回调。

4. 外部调用顺序

假设你在外部调用了以下代码:

provider.rx.request(.getUserInfo(userId: "123")).asObservable().mapObject(User.self).subscribe { event inswitch event {case .next(let data):print("User Info: \(data)")case .error(let error):print("Request failed: \(error)")case .completed:print("Completed")}}.disposed(by: disposeBag)

调用流程:

​ 1. provider.rx.request(.getUserInfo(userId: “123”)) 发起网络请求,返回一个 Observable。

​ 2. asObservable() 将 Single 转换为 Observable。

​ 3. mapObject(User.self) 将响应的 JSON 字符串转换为 User 对象。

​ 4. subscribe 方法订阅 Observable,并传入一个闭包来处理 next、error 和 completed 事件。

​ • 如果请求成功,next 事件会被触发,data 会是一个 User 对象。

​ • 如果请求失败,error 事件会被触发,error 参数为错误信息。

​ • completed 事件会在请求完成时触发。

5. 内存管理

.disposed(by: disposeBag)

​ • disposeBag 用于管理订阅的生命周期,确保在视图控制器销毁时取消订阅,防止内存泄漏。

总结

​ • 外部代码通过 provider.rx.request() 发起请求,接着通过 mapObject 转换响应数据。

​ • subscribe 方法将请求的成功和失败回调传递给 HttpObserver,并处理事件。

​ • HttpObserver 根据响应的 status 来决定调用 success 或处理错误。

​ • 内部错误处理通过 handlerResponse 实现,允许开发者自定义错误处理逻辑。

相关文章:

Moya 网络框架

Moya 网络框架 通过 Moya 进行网络请求的一般步骤如下&#xff1a; 1. 定义 TargetType&#xff1a;为每个 API 请求创建一个枚举&#xff0c;遵循 TargetType 协议&#xff0c;指定基础 URL、请求路径、方法、参数等。 2. 创建 MoyaProvider&#xff1a;实例化 MoyaProvider&…...

FreeRTOS第3篇:链表的“精密齿轮”——列表与列表项

文章目录 1 列表与列表项:FreeRTOS的“排队系统”2 列表操作:FreeRTOS的“排队算法”3 列表的应用场景:FreeRTOS的“任务调度枢纽”4 源码级洞察:列表的“灵魂代码”5 实战:列表操作实验6 总结与思考引言:嵌入式系统的“任务候车厅” 想象你正在管理一座繁忙的火车站:乘…...

React.memo 使用详解与最佳实践

React.memo 使用详解与最佳实践 引言React.memo 是什么&#xff1f;使用场景实战示例示例解析自定义比较函数使用注意事项总结 引言 在 React 应用程序中&#xff0c;性能优化是一个永恒的话题。当父组件状态发生变化时&#xff0c;即使子组件的 props 没有改变&#xff0c;子…...

SpringBoot中集成SaToken

SpringBoot中集成SaToken 1. 写一个拦截器2. 对拦截器的说明&解释2. 拦截器 1. 写一个拦截器 import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.stp.StpUtil; import org.springframework.beans.factory.annotation.Value; import org.spri…...

网络安全-攻击流程-应用层

应用层攻击针对OSI模型的第七层&#xff08;应用层&#xff09;&#xff0c;主要利用协议漏洞、业务逻辑缺陷或用户交互弱点&#xff0c;直接威胁Web应用、API、数据库等服务。以下是常见应用层攻击类型及其流程&#xff0c;以及防御措施&#xff1a; 1. SQL注入&#xff08;SQ…...

Ubuntu 24.04.1 LTS 本地部署 DeepSeek 私有化知识库

文章目录 前言工具介绍与作用工具的关联与协同工作必要性分析 1、DeepSeek 简介1.1、DeepSeek-R1 硬件要求 2、Linux 环境说明2.1、最小部署&#xff08;Ollama DeepSeek&#xff09;2.1.1、扩展&#xff08;非必须&#xff09; - Ollama 后台运行、开机自启&#xff1a; 2.2、…...

微信小程序中缓存数据全方位解惑

微信小程序中缓存数据全方位解惑 微信小程序中的数据缓存是提升用户体验和优化性能的重要手段&#xff0c;跟电脑浏览器中的Local Storage的性质一样。以下是关于微信小程序数据缓存的相关知识点和示例的详细介绍&#xff1a; 1. 数据缓存的类型 微信小程序提供了两种数据缓…...

python语言进阶之函数

目录 前言 函数的创建和调用 函数创建 调用函数 参数传递 形式参数和实际参数 位置参数 数量必须与定义时一致 位置必须与定义时一致 关键字参数 为参数设置默认值 可变参数 **parameter 返回值 变量的作用域 局部变量 全局变量 匿名函数 前言 提到函数&…...

Mybatis-扩展功能

逻辑删除乐观锁 MyBatisPlus从入门到精通-3&#xff08;含mp代码生成器&#xff09; Db静态工具类 Spring依赖循环问题 代码生成器 MybatisPlus代码生成器 枚举处理器 我们这里用int来存储状态 需要注解&#xff0c;很不灵活 希望用枚举类来代替这个Integer 这样的话我…...

青少年编程与数学 02-009 Django 5 Web 编程 16课题、权限管理

青少年编程与数学 02-009 Django 5 Web 编程 16课题、权限管理 一、授权授权的主要特点和作用授权的类型应用场景 二、权限系统使用Django内置的权限系统使用组管理权限使用第三方库在视图中应用权限 三、权限管理示例步骤 1: 创建Django项目和应用步骤 2: 定义模型和权限步骤 …...

Baklib知识中台构建企业智能运营核心架构

内容概要 在数字化转型的浪潮中&#xff0c;企业对于知识的系统化管理需求日益迫切。Baklib作为新一代的知识中台&#xff0c;通过构建智能运营核心架构&#xff0c;为企业提供了一套从知识汇聚到场景化落地的完整解决方案。其核心价值在于将分散的知识资源整合为统一的资产池…...

Java爬虫获取1688商品搜索API接口的实现指南

在电商数据分析、市场调研以及商品选品等领域&#xff0c;按关键字搜索1688商品并获取相关数据是一项重要的任务。本文将详细介绍如何使用Java爬虫技术&#xff0c;通过1688的API接口按关键字搜索商品&#xff0c;并解析返回的数据。以下是实现的完整步骤和代码示例。 一、前期…...

Ubuntu启动geteck/jetlinks实战:Docker启动

参考&#xff1a; JetLinks 物联网基础平台 安装Docker Ubuntu下载安装Docker-Desktop-CSDN博客 sudo apt install -y docker-compose 下载源码 # github亦可 git clone https://gitee.com/jetlinks/jetlinks-community.git cd jetlinks-community 启动 cd docker/run-a…...

保姆级GitHub大文件(100mb-2gb)上传教程

GLF&#xff08;Git Large File Storage&#xff09;安装使用 使用GitHub desktop上传大于100mb的文件时报错 The following files are over 100MB. lf you commit these files, you will no longer beable to push this repository to GitHub.com.term.rarWe recommend you a…...

【16届蓝桥杯寒假刷题营】第2期DAY1I

4.有向无环的路径数 - 蓝桥云课 问题描述 给定 N 个节点 M 条边的有向无环图&#xff0c;请你求解有多少条 1 到 N 的路径。 由于答案可能很大&#xff0c;你只需要输出答案对 998244353 取模后的结果。 输入格式 第一行包含 2 个正整数 N,M&#xff0c;表示有向无环图的节…...

WEB安全--SQL注入--PDO与绕过

一、PDO介绍&#xff1a; 1.1、原理&#xff1a; PDO支持使用预处理语句&#xff08;Prepared Statements&#xff09;&#xff0c;这可以有效防止SQL注入攻击。预处理语句将SQL语句与数据分开处理&#xff0c;使得用户输入的数据始终作为参数传递给数据库&#xff0c;而不会直…...

SQL与数据库程序设计

1.1986年&#xff0c;10月美国国家标准局颁布了SQL语言的美国标准&#xff0c;称为SQL86 2.SQL(Structured Query Language)又称为结构化查询语言 3.建立索引的主要目的是加快查找的速度 4.在基本表上建立一个或者多个索引 5. 一个基本表是最多只能建立一个聚簇索引 6.CAL…...

软考高级《系统架构设计师》知识点(五)

计算机网络 网络概述和模型 计算机网络是计算机技术与通信技术相结合的产物&#xff0c;它实现了远程通信、远程信息处理和资源共享。 计算机网络的功能&#xff1a;数据通信、资源共享、管理集中化、实现分布式处理、负载均衡。 网络性能指标&#xff1a;速率、带宽(频带宽度或…...

DeepSeek 助力 Vue 开发:打造丝滑的面包屑导航(Breadcrumbs)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…...

Ubuntu 系统 LVM 逻辑卷扩容教程

Ubuntu 系统 LVM 逻辑卷扩容教程 前言 在 Linux 系统中&#xff0c;LVM&#xff08;Logical Volume Manager&#xff09;是一种逻辑卷管理工具&#xff0c;允许管理员动态调整磁盘空间&#xff0c;而无需重启系统。 本文将详细介绍如何使用 LVM 扩容逻辑卷&#xff0c;以实现…...

美团一面,有点难度。

一位粉丝朋友分享了最近参与美团民宿旅游业务线的一面的经历&#xff0c;全程约1小时&#xff0c;面试官围绕高并发、分布式事务、性能优化等高频考点展开追问&#xff0c;问题密集且注重落地细节。以下是完整问题整理回答思路扩展解析&#xff0c;助你避坑&#xff01; 一、项…...

7-Zip Final绿色版:高效压缩解压缩工具

在工作与学习旅程中&#xff0c;我们时常需要与各式各样的文件和文件夹打交道。为了更有效地利用存储空间或促进文件的便捷传输&#xff0c;压缩与解压工具自然而然地成为了我们不可或缺的助手。在众多同类工具中&#xff0c;7-Zip凭借其高效能、免费及开源的特性&#xff0c;深…...

详解如何使用Pytest内置Fixture tmp_path 管理临时文件

关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理&#xff0c;构建成功的基石 在自动化测试工作之前&#xff0c;你应该知道的10条建议 在自动化测试中&#xff0c;重要的不是工具 临时目录在测试中起着至关重要的作用&#xff0c;它为执行和验证代码提供了一个可控…...

QML使用ChartView绘制饼状图

一、工程配置 首先修改CMakeLists.txt&#xff0c;按下图修改&#xff1a; find_package(Qt6 6.4 REQUIRED COMPONENTS Quick Widgets) PRIVATEtarget_link_libraries(appuntitledPRIVATE Qt6::QuickPRIVATE Qt6::Widgets )其次修改main.cpp&#xff0c;按下图修改&#xff…...

用大模型学大模型03-数学基础 概率论 最大似然估计(MLE)最大后验估计(MAP)

https://metaso.cn/s/r4kq4Ni 什么是最大似然估计&#xff08;MLE&#xff09;最大后验估计&#xff08;MAP&#xff09;&#xff1f;深度学习中如何应用&#xff0c;举例说明。 好的&#xff0c;我现在需要回答关于最大似然估计&#xff08;MLE&#xff09;和最大后验估计&…...

Rust学习总结之结构体(一)

一&#xff1a;结构体定义 定义结构体&#xff0c;需要使用 struct 关键字并为整个结构体提供一个名字。结构体的名字需要描述它所组合的数据的意义。接着&#xff0c;在大括号中&#xff0c;定义每一部分数据的名字和类型&#xff0c;我们称为 字段&#xff08;field&#xf…...

【Android开发】华为手机安装包安装失败“应用是非正式版发布版本,当前设备不支持安装”问题解决

问题描述 我们将Debug版本的安装包发送到手机上安装&#xff0c;会发现华为手机有如下情况 解决办法 在文件gradle.properties中粘贴代码&#xff1a; android.injected.testOnlyfalse 最后点击“Sync now”&#xff0c;等待重新加载gradle资源即可 后面我们重新编译Debug安装…...

Ubuntu添加桌面快捷方式

以idea为例 一. 背景 在ubuntu中&#xff0c;很多时候是自己解压的文件并没有桌面快捷方式&#xff0c;需要自己找到对应的目录的执行文件手动打开&#xff0c;很麻烦 而只需要在 /usr/share/applications 中创建自定义的desktop文件就能自动复制到桌面 二. 添加方法 创建desk…...

day09_实时类标签/指标

文章目录 day09_实时类标签/指标一、日志数据实时采集2、Flume简介2.3 项目日志数据采集Flume配置2.3.1 涉及的Flume组件和参数2.3.2 Nginx日志采集2.3.3 用户行为日志采集 二、Nginx日志数据统计1、日志格式说明2、数据ETL2.1 日志抽取2.1.1 正则表达式2.1.2 基于Spark实现Ngi…...

排序算法的魔法世界:用C语言揭开数据排列的奥秘

当数据开始跳集体舞:排序的意义 想象你面前有一群调皮的数字精灵在开派对,7和3在跳探戈,9和1在玩捉迷藏,5和2在抢蛋糕。这时候就需要排序算法这位神奇的派对管家出场了!它像音乐指挥家一样挥动魔棒,让所有数字精灵乖乖排成整齐的队伍。在计算机的世界里,排序算法就是处…...