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

Android KMP初探

Android KMP初探

前言:

最近线上听了Kotlin官网举行的KMP会议,感觉听神奇的,于是就把官方demo下载下来尝试了一下,下载插件和所需要的依赖都用了很久,但是发现里面的代码很少,于是尝试自己手写了一下,遇到了不少问题,这里记录一下.

1.定义:

Kotlin Multiplatform 技术可为多种平台创建应用程序并在平台之间高效重用代码,同时保留原生编程的优势。您的应用程序将在 iOS、Android、macOS、Windows、Linux 等平台上运行。

Compose Multiplatform 是 JetBrains 推出的声明式 UI 框架,可让您为 Android、iOS、桌面和 Web 开发共享 UI。将 Compose Multiplatform 集成到 Kotlin Multiplatform 项目中,更快交付应用和功能,而无需维护多个 UI 实现。

在这里插入图片描述

2.适合各类项目:

在这里插入图片描述

3.优点

使用 Compose Multiplatform 只需构建一次 UI

Compose Multiplatform 是一个基于 Kotlin 和 Jetpack Compose 的声明式框架,用于在 Android、iOS、Web 和桌面(通过 JVM)之间共享 UI。

加速 UI 开发

轻松同步多个 UI 实现,让应用更快交付到用户手中。

组件级重用

使用可在所有目标平台上使用的可自定义微件构建您的 UI。使用预设主题快速开始,或自行创建细节可精确至像素的视觉风格。

根据需要使用原生组件

轻松使用原生 UI 微件或将共享 UI 嵌入现有原生应用。

4.需要几个硬性条件:

在使用 KMP + Compose 进行开发时,需要以下条件,由于没有mac设备就暂时不跑ios项目,跑Android项目也是一样的,不用过于纠结.

  • Mac电脑(苹果开发必须mac)
  • Android Studio
  • Xcode
  • 配置 ios 开发环境(cocoapods、开发者账号等)

5.项目结构:

################## 目录结构说明 ##################
```
.
├── README.md
├── app - 主应用
│   ├── build.gradle.kts
│   ├── MainActivity
│   ├── libs
│   └── src
├── commonMain -公共组件
│   ├── app
│   ├── Greeting
│   ├── Platform
├── appleMain - ios平台
│   ├── getPlatform
├── iosMain - ios业务代码
│   ├── MainViewController
│   └── IOSPlatform
├── gradle
│   └── wrapper
├── gradle.properties
├── gradlew
├── gradlew.bat
├── build.gradle.kts
├── local.properties
└── settings.gradle.kts
################## 目录结构说明 ##################

6.App目录下的build.gradle.kts配置:

import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.idea.tcs.extras.isCommonizedKey
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {alias(libs.plugins.kotlinMultiplatform)alias(libs.plugins.androidApplication)alias(libs.plugins.composeMultiplatform)alias(libs.plugins.composeCompiler)
}
kotlin {androidTarget {@OptIn(ExperimentalKotlinGradlePluginApi::class)compilerOptions {jvmTarget.set(JvmTarget.JVM_11)}}listOf(iosX64(),iosArm64(),iosSimulatorArm64()).forEach { iosTarget ->iosTarget.binaries.framework {baseName = "ComposeApp"isStatic = true}}sourceSets {androidMain.dependencies {implementation(compose.preview)implementation(libs.androidx.activity.compose)}commonMain.dependencies {implementation(compose.runtime)implementation(compose.foundation)implementation(compose.material)implementation(compose.ui)implementation(compose.components.resources)implementation(compose.components.uiToolingPreview)implementation(libs.androidx.lifecycle.viewmodel)implementation(libs.androidx.lifecycle.runtime.compose)implementation(libs.androidx.constraintlayout)}}
}android {namespace = "com.cloud.androidkmpdemo"compileSdk = libs.versions.android.compileSdk.get().toInt()defaultConfig {applicationId = "com.cloud.androidkmpdemo"minSdk = libs.versions.android.minSdk.get().toInt()targetSdk = libs.versions.android.targetSdk.get().toInt()versionCode = 1versionName = "1.0"}packaging {resources {excludes += "/META-INF/{AL2.0,LGPL2.1}"}}buildTypes {getByName("release") {isMinifyEnabled = false}}compileOptions {sourceCompatibility = JavaVersion.VERSION_11targetCompatibility = JavaVersion.VERSION_11}compose.desktop {application {mainClass = "com.example.composeApp.MainKt"nativeDistributions {targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)packageName = "com.cloud.kmpdemo"packageVersion = "1.0.0"// 描述应用程序description = "A simple demo for KMP"// 版权信息copyright = "© 2024 My Name. All rights reserved."// 厂商信息vendor = "Example vendor"// 设置许可证文件licenseFile.set(project.file("LICENSE.txt"))}}}
}
dependencies {debugImplementation(compose.uiTooling)
}

7.项目的build.gradle.kts配置:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {alias(libs.plugins.androidApplication) apply falsealias(libs.plugins.androidLibrary) apply falsealias(libs.plugins.composeMultiplatform) apply falsealias(libs.plugins.composeCompiler) apply falsealias(libs.plugins.kotlinMultiplatform) apply falsealias(libs.plugins.jetbrainsKotlinAndroid) apply false
}

8.统一的依赖配置:

[versions]
agp = "8.5.2"
android-compileSdk = "34"
android-minSdk = "24"
android-targetSdk = "34"
androidx-activityCompose = "1.9.3"
androidx-appcompat = "1.7.0"
androidx-constraintlayout = "2.2.0"
androidx-core-ktx = "1.15.0"
androidx-espresso-core = "3.6.1"
androidx-lifecycle = "2.8.4"
androidx-material = "1.12.0"
androidx-test-junit = "1.2.1"
compose-multiplatform = "1.7.0"
junit = "4.13.2"
kotlin = "2.1.0"
kotlinVersion = "1.9.0"[libraries]
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" }
androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-espresso-core" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" }
androidx-material = { group = "com.google.android.material", name = "material", version.ref = "androidx-material" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" }
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" }
androidx-lifecycle-viewmodel = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "androidx-lifecycle" }
androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
androidLibrary = { id = "com.android.library", version.ref = "agp" }
composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" }
composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlinVersion" }

9.公共组件:

9.1 Platform接口:

interface Platform {val name: String
}expect fun getPlatform(): Platform

9.2 Greeting类:

class Greeting {private val platform = getPlatform()fun greet(): String {return "Hello, ${platform.name}!"}
}

9.3 App类:

package com.cloud.kmpdemoimport androidkmpdemo.app.generated.resources.Res
import androidkmpdemo.app.generated.resources.compose_multiplatform
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.AlertDialog
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.ui.tooling.preview.Preview@Composable
@Preview
fun App() {MaterialTheme {var showContent by remember { mutableStateOf(false) }var showDialog by remember { mutableStateOf(false) }Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {Button(onClick = { showContent = !showContent }) {Text("Click me")}Button(onClick = { showDialog = !showDialog }) {Text("show Dialog")}AnimatedVisibility(showContent) {val greeting = remember { Greeting().greet() }Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {Image(painterResource(Res.drawable.compose_multiplatform), null)Text("Compose: $greeting")}}AnimatedVisibility(showDialog) {Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {AlertDialogSample()}}}}
}@Composable
@Preview
fun AlertDialogSample(){val dialog = remember { mutableStateOf(true) }if(dialog.value){AlertDialog(onDismissRequest = { dialog.value = false},title = { Text(text = "开启位置服务")},text = { Text(text = "这将意味着,我们会给您提供精准的位置服务,并且您将接受关于您订阅的位置信息。") },confirmButton = {TextButton(onClick = { dialog.value = false}){Text(text = "同意")}},dismissButton = {TextButton(onClick = {dialog.value = false}){Text(text = "取消")}})}
}

10.Android代码:

本文我在原来的基础上加入了一个弹框示例AlertDialogSample()

package com.cloud.kmpdemoimport android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Previewclass MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent(){App()}}
}@Preview
@Composable
fun AppAndroidPreview() {App()
}@Preview
@Composable
fun DialogAndroidPreview() {//显示dialogAlertDialogSample()
}
package com.cloud.kmpdemoimport android.os.Build/*** 获取平台版本信息*/
class AndroidPlatform : Platform {override val name: String = "Android ${Build.VERSION.SDK_INT}"
}actual fun getPlatform(): Platform = AndroidPlatform()

11.ios平台代码:

package org.example.kmpdemoimport androidx.compose.ui.window.ComposeUIViewController
import com.cloud.kmpdemo.Appfun MainViewController() = ComposeUIViewController { App() }
package org.example.kmpdemoimport com.cloud.kmpdemo.Platform
import platform.UIKit.UIDeviceclass IOSPlatform: Platform {override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}actual fun getPlatform(): Platform = IOSPlatform()

12.ios业务代码:

import UIKit
import SwiftUI
import ComposeAppstruct ComposeView: UIViewControllerRepresentable {func makeUIViewController(context: Context) -> UIViewController {MainViewControllerKt.MainViewController()}func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}struct ContentView: View {var body: some View {ComposeView().ignoresSafeArea(.keyboard) // Compose has own keyboard handler}
}
import SwiftUI@main
struct iOSApp: App {var body: some Scene {WindowGroup {ContentView()}}
}

info.plist:

和Android的build.gradle配置文件一样,都是管理依赖和第三方库的.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict><key>CFBundleDevelopmentRegion</key><string>$(DEVELOPMENT_LANGUAGE)</string><key>CFBundleExecutable</key><string>$(EXECUTABLE_NAME)</string><key>CFBundleIdentifier</key><string>$(PRODUCT_BUNDLE_IDENTIFIER)</string><key>CFBundleInfoDictionaryVersion</key><string>6.0</string><key>CFBundleName</key><string>$(PRODUCT_NAME)</string><key>CFBundlePackageType</key><string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string><key>CFBundleShortVersionString</key><string>1.0</string><key>CFBundleVersion</key><string>1</string><key>LSRequiresIPhoneOS</key><true/><key>CADisableMinimumFrameDurationOnPhone</key><true/><key>UIApplicationSceneManifest</key><dict><key>UIApplicationSupportsMultipleScenes</key><false/></dict><key>UILaunchScreen</key><dict/><key>UIRequiredDeviceCapabilities</key><array><string>armv7</string></array><key>UISupportedInterfaceOrientations</key><array><string>UIInterfaceOrientationPortrait</string><string>UIInterfaceOrientationLandscapeLeft</string><string>UIInterfaceOrientationLandscapeRight</string></array><key>UISupportedInterfaceOrientations~ipad</key><array><string>UIInterfaceOrientationPortrait</string><string>UIInterfaceOrientationPortraitUpsideDown</string><string>UIInterfaceOrientationLandscapeLeft</string><string>UIInterfaceOrientationLandscapeRight</string></array>
</dict>
</plist>

13.运行效果如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

14.总结:

以上就是今天的内容,KMP初探,根据不同平台的设备显示不同类型和版本号,代码非常少,再也没有创建xml的烦恼,MainActivity也不需要加载activity_main布局,简直不要太爽,当然KMP如果不熟悉的话跑起来很费劲,我是从0到1自己全部重新撸了一遍,包含Android和IOS两个平台,build插件配置等等,这里我没有Mac环境就不演示iOS的效果了.如果只是单纯写代码看效果没有太大的意义,需要搞清楚整个运行过程和实现原理,在后面进行学习和开发过程中就会事半功倍。

15.项目源码地址:

https://gitee.com/jackning_admin/android-kmpdemo

相关文章:

Android KMP初探

Android KMP初探 前言&#xff1a; 最近线上听了Kotlin官网举行的KMP会议&#xff0c;感觉听神奇的&#xff0c;于是就把官方demo下载下来尝试了一下&#xff0c;下载插件和所需要的依赖都用了很久&#xff0c;但是发现里面的代码很少&#xff0c;于是尝试自己手写了一下&…...

ncDLRES:一种基于动态LSTM和ResNet的非编码RNA家族预测新方法

现有的计算方法主要分为两类&#xff1a;第一类是通过学习序列或二级结构的特征来预测ncRNAs家族&#xff0c;另一类是通过同源序列之间的比对来预测ncRNAs家族。在第一类中&#xff0c;一些方法通过学习预测的二级结构特征来预测ncRNAs家族。二级结构预测的不准确性可能会导致…...

前端项目打包过滤指定icon文件

1.需求背景 项目中有部分功能需要vip权限才可以使用&#xff0c;所有部分筛选、按钮 等有vip的icon提示 如下图 此项目衍生出一个特殊版本&#xff0c;此版本无需登录且拥有最高权限&#xff0c;所以产品要求去除项目中的所有vip相关的提示。 2.解决思路 &#xff08;1&am…...

蓝桥杯 Java B 组之最短路径算法(Dijkstra、Floyd-Warshall)

Day 2&#xff1a;最短路径算法&#xff08;Dijkstra、Floyd-Warshall&#xff09; &#x1f4d6; 一、最短路径算法简介 最短路径问题是图论中的经典问题&#xff0c;主要用于求解 单源最短路径 或 多源最短路径。在实际应用中&#xff0c;最短路径广泛应用于 导航系统、网络…...

科普:HTTP端口80和HTTPS端口443

你会发现&#xff0c;有的网址不带端口号&#xff0c;怎么回事&#xff1f; HTTP协议默认端口&#xff1a;HTTP协议的默认端口是80。当用户在浏览器中输入一个没有指定端口的以http://开头的网址时&#xff0c;浏览器会自动使用80端口与服务器建立连接&#xff0c;进行超文本数…...

如何安装vm和centos

安装 VMware Workstation Pro 步骤 1&#xff1a;下载 VMware Workstation Pro 访问 VMware 官方网站&#xff08;Desktop Hypervisor Solutions | VMware &#xff09;&#xff0c;根据你的操作系统选择合适的版本进行下载。 步骤 2&#xff1a;运行安装程序 找到下载的安装…...

鸿蒙-验证码输入框的几种实现方式-上

文章目录 效果图、优缺点多TextInput多 TextCanvas 绘制 多个 TextInput 拼接放置四个输入框焦点移动输入时向后移动输入完成回调删除时向前移动 防止点击总结 最近在做应用鸿蒙化&#xff0c;说白了就是把原来Android、iOS的代码重新用ArkTS写一遍&#xff0c;我负责基础建设和…...

Vi 编辑器基本使用指南

一、Vi 编辑器的启动与退出 启动 Vi 编辑器 在终端中&#xff0c;输入vi加上要编辑的文件名&#xff0c;如vi example.txt&#xff0c;如果example.txt存在&#xff0c;Vi 编辑器会打开该文件&#xff1b;若不存在&#xff0c;则会创建一个新的空文件并打开。如果只输入vi&am…...

centos 7 安装python3 及pycharm远程连接方法

安装openssl 使用pip3安装 virtualenv的时候会提示WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available. 这是因为缺少openssl 2.0以上版本 解决办法&#xff1a; 一、先确认版本 openssl version 二、安…...

PostgreSQL 使用pgAdmin 4 数据库还原sql文件报错问题分析

sql执行报错问题: C:\Program Files\PostgreSQL\17\bin\pg_restore.exe --host "localhost" --port "5433" --username "postgres" --no-password --dbname "ry_postgresql-final" --verbose "E:\\PostgreSQLProject\\Ruoyi-Po…...

gihub上适合练手的Python项目

GitHub 上有许多适合练手的 Python 项目&#xff0c;涵盖了从初学者到中级开发者的不同难度级别。以下是一些推荐的项目类型和具体示例&#xff0c;帮助你提升 Python 编程技能&#xff1a; 1. 基础项目 适合初学者&#xff0c;帮助掌握 Python 基础语法和常用库。 示例项目&…...

3D Web轻量化引擎HOOPS Communicator如何赋能航空航天制造?

在当今航空航天制造领域&#xff0c;精确度、效率和协作是推动行业发展的关键要素。随着数字化技术的飞速发展&#xff0c;3D Web可视化开发包HOOPS Communicator 为航空航天制造带来了革命性的变化。它凭借强大的功能和灵活的应用&#xff0c;助力企业在设计、生产、培训等各个…...

AWQ和GPTQ量化的区别

一、前言 本地化部署deepseek时发现&#xff0c;如果是量化版的deepseek&#xff0c;会节约很多的内容&#xff0c;然后一般有两种量化技术&#xff0c;那么这两种量化技术有什么区别呢&#xff1f; 二、量化技术对比 在模型量化领域&#xff0c;AWQ 和 GPTQ 是两种不同的量…...

通过恒定带宽服务器调度改进时间敏感网络(TSN)流量整形

论文标题 英文标题&#xff1a;Improving TSN Traffic Shaping with Constant Bandwidth Server Scheduling 中文标题&#xff1a;通过恒定带宽服务器调度改进时间敏感网络&#xff08;TSN&#xff09;流量整形 作者信息 作者&#xff1a;Benjamin van Seggelen 指导教师&am…...

气象干旱触发水文(农业)干旱的概率及其触发阈值的动态变化-贝叶斯copula模型

前言 在干旱研究中&#xff0c;一个关键的科学问题是&#xff1a;在某一地区发生不同等级的气象干旱时&#xff0c;气象干旱会以何种概率引发不同等级的水文干旱、农业干旱和地下水干旱&#xff1f;换句话说&#xff0c;气象干旱的不同程度会分别引发其他类型干旱的哪种等级&a…...

自定义Spring Boot Starter(官网文档解读)

摘要 本文将详细介绍自定义 Spring Boot Starter 的完整过程。要构建自定义 Starter&#xff0c;首先需掌握 Spring Boot 中 Auto-configuration 以及相关注解的工作原理&#xff0c;同时了解 Spring Boot 提供的一系列条件注解。在具备这些知识基础后&#xff0c;再按照特定步…...

开发 picgo-plugin-huawei 插件,解决华为云社区外链限制问题

开发 picgo-plugin-huawei 插件&#xff0c;解决华为云社区外链限制问题 在技术博客平台中&#xff0c;外链的使用常常受到限制&#xff0c;这给我们的写作和内容展示带来了一定的不便。为了应对这一问题&#xff0c;我开发了 picgo-plugin-huawei 插件&#xff0c;它能够有效…...

最长回文子串

标题 1.1 问题描述 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 1.2 示例 1.2.1 示例1 输入&#xff1a;s “babad” 输出&#xff1a;“bab” 解释&#xff1a;“aba” 同样是符合题意的答案。 1.2.2 示例2 输入&#xff1a;s “cbbd” 输出&#xff1a;“bb…...

JavaSE学习笔记26-集合(Collection)

集合 Java 中的集合&#xff08;Collection&#xff09;是 Java 标准库中非常重要的一部分&#xff0c;用于存储和操作一组对象。Java 集合框架&#xff08;Java Collections Framework&#xff09;提供了一套丰富的接口和类&#xff0c;用于处理各种数据结构&#xff0c;如列…...

开源神器KRR:用数据驱动K8s资源优化

引言:云原生时代的资源管理之痛 在Kubernetes集群中,过度配置导致资源浪费与配置不足引发稳定性风险的矛盾始终存在。CNCF调研显示,企业平均有35%的云资源处于闲置状态。本文将揭秘开源神器KRR(Kubernetes Resource Recommender),通过数据驱动方式实现精准资源配置,实测…...

微信小程序:多菜单栏设计效果

一、实现效果 二、代码 wxml 编辑前端界面,步骤 菜单逻辑: 逐步取出数组中的项,首先取出顶部菜单项,然后选中后取出选中的底部数据(左侧菜单+右侧内容),然后点击左侧菜单取出选中的左侧菜单对应的右侧内容 ①这里我的数据是全部封装到一个数组对象的,首先我的循环…...

网络安全-js安全知识点与XSS常用payloads

简介 JavaScript 是一种轻量级的编程语言&#xff0c;定义了HTML的行为。它与Java的关系类似周杰和周杰伦的关系&#xff08;即没有关系&#xff09;。 用法 HTML 中的脚本必须位于 <script> 与 </script> 标签之间。 脚本可被放置在 HTML 页面的 <body>…...

无人机实战系列(二)本地摄像头 + Depth-Anything V2

这篇文章介绍了如何在本地运行 Depth-Anything V2&#xff0c;因为我使用的无人机是Tello&#xff0c;其本身仅提供了一个单目视觉相机&#xff0c;在众多单目视觉转 Depth 的方案中我选择了 Depth-Anything V2&#xff0c;这个库的强大在于其基于深度学习模型将单目视觉以较低…...

[杂学笔记]工厂模式、多态、内存空间区域划分、cp指令破坏软连接问题、UDP如何实现可靠传输、滑动窗口的原理、进程与线程、线程之间的通信

目录 1.工厂模式 2.多态 3.内存空间区域划分 4.cp指令破坏软连接问题 5.UDP实现可靠传输 6.滑动窗口的原理 7.进程与线程 8.线程之间的通信 1.工厂模式 工厂模式是一种创建对象的设计模式。它提供了一种创建对象的方式&#xff0c;将对象的创建和使用分离&#xff0c;通…...

【IEEE出版,往届会后3个月EI检索 | 西华大学主办 | 中英文期刊、SCI期刊推荐】第四届能源、电力与电气国际学术会议(ICEPET 2025)

第四届能源、电力与电气国际学术会议&#xff08;ICEPET 2025&#xff09;由西华大学主办&#xff0c;西华大学能源与动力工程学院、西华大学电气与电子信息学院、西华大学航空航天学院、流体及动力机械教育部重点实验室、流体机械及工程四川省重点实验室、四川省水电能源动力装…...

【AI+智造】DeepSeek价值重构:当采购与物控遇上数字化转型的化学反应

作者&#xff1a;Odoo技术开发/资深信息化负责人 日期&#xff1a;2025年2月24日 引言&#xff1a;从事企业信息化工作16年&#xff0c;我见证过无数企业从手工台账到ERP系统的跨越。但真正让采购和物控部门脱胎换骨的&#xff0c;是融合了Deepseek AI的Odoo数字化解决方案——…...

1.适配器模式

概述 适配器模式&#xff1a;将一个类的接口转换成客户希望的另一个接口&#xff0c;使得原本不兼容的类可以一起工作。 适配器模式在业务场景中非常有用&#xff0c;尤其是在系统集成、接口兼容性处理以及代码复用等场景。以下是一个实际的业务场景示例&#xff1a; 业务场景…...

选择排序(详解)c++

选择排序(Selection Sort)是⼀种特别直观的排序算法。每次找出未排序序列中最⼩的元素&#xff0c;然后放进有序序列的后⾯ 算法思想: 每次找出未排序序列中最小的元素&#xff0c;然后放进有序序列的后面 在数组中完成选择排序 落实到代码的时候就两步&#xff1a;找最小交换 …...

[java基础-JVM篇]1_JVM自动内存管理

JVM内存管理涉及但不限于类加载、对象分配、垃圾回收等&#xff0c;本篇主要记录运行时数据区域与对象相关内容。 内容主要来源《深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践》与官方文档&#xff0c;理解与表述错漏之处恳请各位大佬指正。 目录 运行时数据区域 栈 栈…...

python-leetcode 42.验证二叉搜索树

题目&#xff1a; 给定二叉树的根节点root,判断是否是一个有效二叉搜索树 有效二叉搜索树&#xff1a; 1.节点的左子树只包含小于当前节点的树 2.节点的右子树只包含大于当前节点的树 3.所有左子树和右子树自身必须也是二叉搜索树 方法一&#xff1a;递归 如果该二叉树的…...

Unity Shader 学习13:屏幕后处理 - 使用高斯模糊的Bloom辉光效果

目录 一、基本的后处理流程 - 以将画面转化为灰度图为例 1. C#调用shader 2. Shader实现效果 二、Bloom辉光效果 1. 主要变量 2. Shader效果 &#xff08;1&#xff09;提取较亮区域 - pass1 &#xff08;2&#xff09;高斯模糊 - pass2&3 &#xff08;3&#xff…...

【Bluedroid】AVRCP 连接源码分析(三)

接着上一篇【Bluedroid】AVRCP 连接源码分析(一)-CSDN博客,继续AVRCP连接的源码分析。 AVRC_OpenBrowse /packages/modules/Bluetooth/system/stack/avrc/avrc_api.cc /******************************************************************************** Function …...

图数据库Neo4j面试内容整理-约束(Constraint)

约束(Constraint) 是数据库中用于确保数据一致性和完整性的一种机制。它限制了数据的某些方面,确保特定条件得到满足。在 Neo4j 中,约束主要用于确保图数据的一致性,防止插入不符合规则的数据。约束通常与索引一起使用,但它们的功能和目的有所不同。 1. Neo4j 中的约束类…...

QUdpSocket的readyRead信号只触发一次

问题 QUdpSocket的readyRead信号只触发一次。 原因 on_readyRead槽函数里必须读出现有数据后&#xff0c;才能触发新的事件。 解决办法 在on_readyRead槽函数里取出数据。 void MainWindow::on_readyRead() {qDebug() << "on_readyRead in";while (m_udp…...

使用Windbg调试目标进程排查C++软件异常的一般步骤与要点分享

目录 1、概述 2、将Windbg附加到已经启动起来的目标进程上&#xff0c;或者用Windbg启动目标程序 2.1、将Windbg附加到已经启动起来的目标进程上 2.2、用Windbg启动目标程序 2.3、Windbg关联到目标进程上会中断下来&#xff0c;输入g命令将该中断跳过去 3、分析实例说明 …...

深度解析:大模型在多显卡服务器下的通信机制与分布式训练——以DeepSeek、Ollama和vLLM为例

一、引言&#xff1a;大模型与多显卡的必然结合 随着大模型参数规模突破千亿级&#xff08;如GPT-4、DeepSeek&#xff09;&#xff0c;单显卡的显存容量与算力已无法满足需求。多显卡并行计算成为训练与推理的核心技术&#xff0c;其核心挑战在于高效通信与负载均衡。本文以国…...

爬虫基础入门之爬取豆瓣电影Top250-Re正则的使用

网址:豆瓣电影 Top 250 本案例所需要的模块 requests (用于发送HTTP请求)re (用于字符串匹配和操作) 确定需要爬取的数据 &#xff1a; 电影的名称电影的年份电影的评分电影评论人数 一. 发送请求 模拟浏览器向服务器发送请求 准备工作 -分析页面: F12 or 右击点击检查 查看…...

【R安装包报错】在conda环境下用R语言命令安装R包报错

报错如下&#xff1a; gnu/include/c/11.2.0/ctime:80:11: error: ‘timespec_get’ has not been declared in ‘::’ 80 | using ::timespec_get; | ^~~~~~~~~~~~ 修改 报错原因&#xff1a;如果使用的是conda安装的g&#xff0c;可能与系统库不兼容。尝试 切换到系统默认编…...

基于STM32单片机设计的宠物喂食监控系统

1. 项目开发背景 随着宠物数量的增加&#xff0c;尤其是人们对宠物的养护需求日益增多&#xff0c;传统的人工喂养和管理方式难以满足现代养宠生活的需求。人们越来越希望通过智能化手段提高宠物养护的质量和效率&#xff0c;特别是对于宠物喂食、饮水、温湿度控制等方面的智能…...

Minio分布式多节点多驱动器集群部署

Minio分布式多节点多驱动器集群部署 Minio分布式多节点多驱动器集群部署节点规划先决条件开放防火墙端口设置主机名更新域名映射文件时间同步存储要求内存要求 增加虚拟机磁盘(所有机器都要执行)部署分布式 MinIO测试上传与预览测试高可用MinIO 配置限制模拟单节点磁盘故障模拟…...

Web前端开发——HTML基础

本系列博客声明&#xff0c;根据本人所学书籍和网上的一些资料共同磨合&#xff0c;写下web前端系列的博客 HTML基础 一、HTML基本概述[^1]二、HTML大体认知1.HTML基本结构2.HTML 语法格式 三、THML常用标记[^2]1.文本标记&#xff08;1&#xff09;标题&#xff08;2&#xf…...

《计算机视觉》——图像拼接

图像拼接 图像拼接是将多幅有重叠区域的图像合并成一幅全景或更大视角图像的技术&#xff0c;以下为你详细介绍&#xff1a; 原理&#xff1a;图像拼接的核心原理是基于图像之间的特征匹配。首先&#xff0c;从每幅图像中提取独特的特征点&#xff0c;如角点、边缘点等&#x…...

zookeeper从入门到精通

一、入门基础 1.1 什么是 ZooKeeper ZooKeeper 是一个开源的分布式协调服务&#xff0c;由雅虎创建&#xff0c;后成为 Apache 的顶级项目。它为分布式应用提供了高效、可靠的协调服务&#xff0c;例如统一命名服务、配置管理、分布式锁、集群管理等。ZooKeeper 的数据模型类…...

2.2 添加注释

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 注释是为了方便理解代码含义而添加的简短的解释性说明。在编译时&#xff0c;编辑器不会将注释加入最终生成的文件中&#xff0c;不…...

具有快慢思考的语言调节机器人操作

24年1月来自华东师范大学、美的集团和上海大学的论文“Language-Conditioned Robotic Manipulation with Fast and Slow Thinking”。 语言调节机器人操作&#xff0c;旨在将自然语言指令转化为可执行动作&#xff0c;从简单的“拾取和放置”到需要意图识别和视觉推理的任务。…...

美颜相机1.0

项目开发步骤 1 界面开发 美颜相机界面构成&#xff1a; 标题 尺寸 关闭方式 位置 可视化 2 创建主函数调用界面方法 3 添加两个面板 一个是按钮面板一个是图片面板 用JPanel 4 添加按钮到按钮面吧【注意&#xff1a;此时要用初始化按钮面板的方法initBtnPanel 并且将按钮添…...

Css3重点知识讲解

选择器 优先级&#xff1a; id 选择器 > 类选择器 > 标签选择器 类选择器&#xff1a; .myClass {color: blue; }id 选择器&#xff08;全局唯一&#xff09;&#xff1a; #myId {color: green; }标签选择器&#xff1a; p {color: red; }层次选择器&#xff1a; /…...

[Web 安全] Web 安全攻防 - 学习手册

关联专栏&#xff1a;[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01&#xff1a;Web 安全攻防 —— 信息收集篇 Web 信息收集 — 手动收集域名信息 Web 信息收集 — 手动收集 IP 信息 Web 信息收集 — 端口服务信息收集 Web 信息收集 — 自动化信息收集 — ShuiZe 水泽 We…...

nextjs的记录一些小东西

1. 格式化时间&#xff1a;使用date-fns库 npm install date-fns 在组建中创建date.js import { parseISO, format } from date-fnsexport default function Date({ dateString }) {const date parseISO(dateString)return <time dateTime{dateString}>{format(date,…...

故障诊断 | PID搜索算法优化CatBoost故障诊断(MatlabPython)

目录 效果一览文章概述故障诊断 | PID搜索算法优化CatBoost故障诊断(Matlab&Python)PID搜索算法优化CatBoost故障诊断PID搜索算法优化CatBoost故障诊断一、引言1.1、研究背景与意义1.2、研究现状1.3、研究目的与内容二、CatBoost算法概述2.1、CatBoost算法原理2.2、CatBo…...