广告轮播是移动应用中提升用户转化率的核心组件,尤其在电商、资讯类应用中应用广泛。传统轮播仅支持图片展示,而现代应用需要兼顾图片和视频内容以增强吸引力。本文将详细讲解如何实现一个支持图片与视频混合播放的高性能广告轮播,涵盖布局设计、媒体加载、自动轮播、生命周期管理等关键技术点,并提供可直接复用的代码方案。

一、核心组件与技术选型

实现混合媒体轮播需要解决三个核心问题:不同类型媒体的统一管理、视频播放的资源控制、轮播切换的流畅性。选择合适的技术栈是实现的基础。

1.1 核心组件选择

组件

选型方案

优势

轮播容器

ViewPager2

支持垂直 / 水平滑动、 RecyclerView 复用机制、页面 Transformer

图片加载

Coil

Kotlin 友好、支持 GIF、自动内存管理

视频播放

ExoPlayer

支持多种格式、低延迟、资源控制精细

生命周期管理

LifecycleObserver

自动感知组件生命周期,释放资源

缓存策略

三级缓存(内存 + 磁盘 + 网络)

减少重复请求,提升加载速度

1.2 媒体数据模型设计

统一图片和视频的数据模型,便于适配器统一处理:

// 媒体类型枚举
enum class MediaType {IMAGE, VIDEO
}// 广告数据模型
data class AdMedia(val id: String,val url: String, // 图片或视频URLval type: MediaType,val duration: Long = 5000 // 展示时长(毫秒),视频可使用自身时长
)// 示例数据
val testAds = listOf(AdMedia("1", "https://example.com/banner1.jpg", MediaType.IMAGE),AdMedia("2", "https://example.com/promo.mp4", MediaType.VIDEO),AdMedia("3", "https://example.com/banner2.jpg", MediaType.IMAGE)
)

二、基础布局与轮播容器实现

轮播的基础结构由三部分组成:ViewPager2 容器、媒体展示项、页码指示器。合理的布局设计是实现流畅体验的前提。

2.1 主布局设计

<!-- res/layout/layout_ad_carousel.xml -->
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="200dp"><!-- 轮播容器 --><androidx.viewpager2.widget.ViewPager2android:id="@+id/viewPager"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"/><!-- 页码指示器 --><LinearLayoutandroid:id="@+id/indicatorContainer"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"android:spacing="8dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintBottom_margin="16dp"/></androidx.constraintlayout.widget.ConstraintLayout>

2.2 媒体项布局(图片与视频共用)

<!-- res/layout/item_media_container.xml -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><!-- 图片容器 --><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/ivImage"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"android:visibility="gone"/><!-- 视频容器 --><FrameLayoutandroid:id="@+id/videoContainer"android:layout_width="match_parent"android:layout_height="match_parent"android:visibility="gone"><!-- ExoPlayer的SurfaceView --><com.google.android.exoplayer2.ui.StyledPlayerViewandroid:id="@+id/playerView"android:layout_width="match_parent"android:layout_height="match_parent"android:keepScreenOn="true"/><!-- 视频加载中指示器 --><ProgressBarandroid:id="@+id/progressBar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:visibility="gone"/></FrameLayout></FrameLayout>

三、核心适配器实现

ViewPager2 的适配器需要处理两种视图类型(图片 / 视频),并实现高效的复用机制。关键在于分离媒体加载逻辑,确保资源正确释放。

3.1 适配器基础结构

class MediaCarouselAdapter(private val lifecycle: Lifecycle, // 用于绑定播放器生命周期private val ads: List<AdMedia>
) : RecyclerView.Adapter<MediaCarouselAdapter.MediaViewHolder>() {// 视图类型:图片=0,视频=1override fun getItemViewType(position: Int): Int {return when (ads[position].type) {MediaType.IMAGE -> 0MediaType.VIDEO -> 1}}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MediaViewHolder {val view = LayoutInflater.from(parent.context).inflate(R.layout.item_media_container, parent, false)return MediaViewHolder(view, viewType, lifecycle)}override fun onBindViewHolder(holder: MediaViewHolder, position: Int) {holder.bind(ads[position])}override fun getItemCount() = ads.size// 视图持有者class MediaViewHolder(itemView: View,viewType: Int,lifecycle: Lifecycle) : RecyclerView.ViewHolder(itemView) {// 视图绑定与媒体加载逻辑(见3.2、3.3节)}// 回收资源override fun onViewRecycled(holder: MediaViewHolder) {super.onViewRecycled(holder)holder.release()}
}

3.2 图片加载实现

使用 Coil 加载图片,支持自动缓存和生命周期管理:

// 在MediaViewHolder中
private val imageView: AppCompatImageView = itemView.findViewById(R.id.ivImage)private fun bindImage(ad: AdMedia) {// 显示图片视图,隐藏视频视图imageView.visibility = View.VISIBLEvideoContainer.visibility = View.GONE// 使用Coil加载图片Coil.imageLoader(itemView.context).enqueue(ImageRequest.Builder(itemView.context).data(ad.url).target(imageView).crossfade(true).placeholder(R.drawable.ic_ad_placeholder).error(R.drawable.ic_ad_error).listener(onSuccess = { request, metadata ->// 图片加载成功回调},onError = { request, throwable ->Log.e("ImageLoad", "加载失败", throwable)}).build())
}

3.3 视频播放实现

基于 ExoPlayer 实现视频加载与播放控制,关键在于与生命周期绑定:

// 在MediaViewHolder中
private val videoContainer: FrameLayout = itemView.findViewById(R.id.videoContainer)
private val playerView: StyledPlayerView = itemView.findViewById(R.id.playerView)
private val progressBar: ProgressBar = itemView.findViewById(R.id.progressBar)
private var player: ExoPlayer? = null
private var mediaItem: MediaItem? = null
private var isPlaying = false// 初始化播放器
private fun initPlayer(lifecycle: Lifecycle) {if (player == null) {val context = itemView.context// 创建播放器实例player = ExoPlayer.Builder(context).build()playerView.player = player// 绑定生命周期,自动释放资源lifecycle.addObserver(object : LifecycleObserver {@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)fun onPause() {player?.pause()isPlaying = false}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)fun onDestroy() {releasePlayer()}})}
}// 加载并播放视频
private fun bindVideo(ad: AdMedia) {// 显示视频视图,隐藏图片视图videoContainer.visibility = View.VISIBLEimageView.visibility = View.GONEprogressBar.visibility = View.VISIBLEinitPlayer(lifecycle)mediaItem = MediaItem.fromUri(ad.url)player?.apply {setMediaItem(mediaItem!!)prepare()addListener(object : Player.Listener {override fun onPlaybackStateChanged(state: Int) {if (state == Player.STATE_READY) {progressBar.visibility = View.GONEplay()isPlaying = true} else if (state == Player.STATE_ERROR) {progressBar.visibility = View.GONE}}override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {isPlaying = playWhenReady}})}
}// 释放视频资源
private fun releasePlayer() {player?.stop()player?.release()player = nullplayerView.player = nullisPlaying = false
}

3.4 绑定媒体数据

在 ViewHolder 中根据类型分发处理:

// 在MediaViewHolder中
fun bind(ad: AdMedia) {when (ad.type) {MediaType.IMAGE -> bindImage(ad)MediaType.VIDEO -> bindVideo(ad)}
}// 回收资源
fun release() {when (ads[adapterPosition].type) {MediaType.IMAGE -> {// 取消图片加载请求Coil.imageLoader(itemView.context).cancelAll()}MediaType.VIDEO -> {releasePlayer()}}
}

四、自动轮播与交互控制

自动轮播需要实现定时切换、用户交互暂停、循环播放等功能,同时处理视频播放时的特殊逻辑。

4.1 自动轮播核心逻辑

class AutoCarouselManager(private val viewPager: ViewPager2,private val ads: List<AdMedia>,private val interval: Long = 5000 // 默认5秒切换一次
) {private val handler = Handler(Looper.getMainLooper())private val carouselRunnable = object : Runnable {override fun run() {val current = viewPager.currentItemval next = (current + 1) % ads.sizeviewPager.setCurrentItem(next, true)handler.postDelayed(this, getNextDelay(next))}}// 根据媒体类型获取下一次延迟时间(视频使用自身时长)private fun getNextDelay(position: Int): Long {return if (ads[position].type == MediaType.VIDEO) {ads[position].duration // 视频使用预设时长或实际时长} else {interval // 图片使用默认间隔}}// 开始自动轮播fun start() {stop() // 先停止再启动,避免重复handler.postDelayed(carouselRunnable, getNextDelay(viewPager.currentItem))}// 停止自动轮播fun stop() {handler.removeCallbacks(carouselRunnable)}// 跟随生命周期管理fun attachToLifecycle(lifecycle: Lifecycle) {lifecycle.addObserver(object : LifecycleObserver {@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)fun onResume() {start()}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)fun onPause() {stop()}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)fun onDestroy() {stop()}})}
}

4.2 用户交互处理

当用户触摸轮播时暂停自动播放,结束触摸后恢复:

// 在轮播初始化时设置触摸监听
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {override fun onPageSelected(position: Int) {// 更新指示器updateIndicator(position)// 重置自动轮播计时器autoCarouselManager.stop()autoCarouselManager.start()}
})// 触摸监听:按下时停止,抬起时恢复
viewPager.setOnTouchListener { _, event ->when (event.action) {MotionEvent.ACTION_DOWN -> {autoCarouselManager.stop()}MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {autoCarouselManager.start()}}false // 不消费事件,确保滑动正常
}

4.3 页码指示器实现

动态创建指示器点,并在页面切换时更新状态:

private fun initIndicator(container: LinearLayout, count: Int) {// 清除现有指示器container.removeAllViews()// 创建指示器点repeat(count) {val indicator = View(container.context).apply {layoutParams = LinearLayout.LayoutParams(8.dp, 8.dp).apply {gravity = Gravity.CENTER}setBackgroundResource(R.drawable.selector_indicator)isSelected = it == 0 // 默认第一个选中}container.addView(indicator)}
}private fun updateIndicator(position: Int) {val count = indicatorContainer.childCountfor (i in 0 until count) {indicatorContainer.getChildAt(i).isSelected = i == position}
}// 指示器选择器(res/drawable/selector_indicator.xml)
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@drawable/indicator_selected" android:state_selected="true"/><item android:drawable="@drawable/indicator_normal"/>
</selector>

五、性能优化与资源管理

混合媒体轮播容易出现内存泄漏和性能问题,需要针对性优化。

5.1 内存优化策略

1.图片缓存控制

// 配置Coil缓存策略
val imageLoader = ImageLoader.Builder(context).memoryCachePolicy(CachePolicy.ENABLED).diskCachePolicy(CachePolicy.ENABLED).diskCache(DiskCache.Builder().directory(context.cacheDir.resolve("image_cache")).maxSizeBytes(512L * 1024 * 1024) // 512MB缓存上限.build()).build()

2.视频资源回收

// 在适配器的onViewRecycled中强制释放
override fun onViewRecycled(holder: MediaViewHolder) {super.onViewRecycled(holder)holder.release() // 调用前面实现的release方法
}// 限制ViewPager2的缓存页数
viewPager.offscreenPageLimit = 1 // 只缓存当前页和相邻页

3.避免大型 Bitmap

// 加载图片时指定尺寸(与轮播控件匹配)
ImageRequest.Builder(context).size(1080, 600) // 与轮播容器尺寸一致.scale(Scale.FILL).build()

5.2 播放体验优化

1.视频预加载

// 在ViewPager2中预加载下一个视频
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {override fun onPageSelected(position: Int) {val nextPos = (position + 1) % ads.sizeif (ads[nextPos].type == MediaType.VIDEO) {// 预加载下一个视频(仅准备,不播放)preloadVideo(ads[nextPos].url)}}
})

2.视频静音播放

// 默认静音播放,提升用户体验
playerView.controllerShowTimeoutMs = 0 // 隐藏控制器
player?.volume = 0f // 静音

3.滑动时暂停视频

// 页面滚动时暂停所有视频
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {override fun onPageScrollStateChanged(state: Int) {when (state) {ViewPager2.SCROLL_STATE_DRAGGING -> {// 开始滑动,暂停所有可见视频pauseVisibleVideos()}ViewPager2.SCROLL_STATE_IDLE -> {// 滑动结束,恢复当前视频播放resumeCurrentVideo()}}}
})

5.3 异常处理

1.网络状态适配

// 监听网络变化,弱网环境下优先加载图片
private val networkCallback = object : ConnectivityManager.NetworkCallback() {override fun onNetworkCapabilitiesChanged(network: Network,capabilities: NetworkCapabilities) {val isMetered = connectivityManager.isActiveNetworkMeteredval isLowBandwidth = !capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_HIGH_BANDWIDTH)if (isMetered || isLowBandwidth) {// 弱网环境,替换视频为封面图replaceVideosWithCovers()}}
}

2.错误重试机制

// 视频加载失败时重试
private fun setupRetry机制(player: ExoPlayer) {var retryCount = 0player.addListener(object : Player.Listener {override fun onPlayerError(error: PlaybackException) {if (retryCount < 3) { // 最多重试3次retryCount++player.prepare()} else {// 重试失败,显示错误图片showVideoErrorPlaceholder()}}})
}

六、完整集成示例

将上述组件整合到 Activity 或 Fragment 中:

class AdCarouselActivity : AppCompatActivity() {private lateinit var binding: LayoutAdCarouselBindingprivate lateinit var adapter: MediaCarouselAdapterprivate lateinit var autoCarouselManager: AutoCarouselManageroverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = LayoutAdCarouselBinding.inflate(layoutInflater)setContentView(binding.root)// 初始化数据val ads = getAdData()// 初始化适配器adapter = MediaCarouselAdapter(lifecycle, ads)binding.viewPager.adapter = adapter// 初始化指示器initIndicator(binding.indicatorContainer, ads.size)// 初始化自动轮播autoCarouselManager = AutoCarouselManager(binding.viewPager, ads)autoCarouselManager.attachToLifecycle(lifecycle)// 页面切换监听binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {override fun onPageSelected(position: Int) {updateIndicator(position)}})// 启动轮播autoCarouselManager.start()}private fun getAdData(): List<AdMedia> {// 实际项目中从网络或本地获取return testAds}override fun onDestroy() {super.onDestroy()// 手动释放资源(双重保障)autoCarouselManager.stop()}
}

七、扩展功能与最佳实践

7.1 常用扩展功能

1.轮播动画

// 设置页面切换动画
binding.viewPager.setPageTransformer(DepthPageTransformer())// 深度动画实现
class DepthPageTransformer : ViewPager2.PageTransformer {override fun transformPage(page: View, position: Float) {page.apply {val pageWidth = widthwhen {position < -1 -> alpha = 0fposition <= 0 -> {alpha = 1ftranslationX = 0f}position <= 1 -> {alpha = 1 - positiontranslationX = pageWidth * -position}else -> alpha = 0f}}}
}

2.点击事件处理

// 在适配器中设置点击监听
class MediaCarouselAdapter(private val onAdClick: (AdMedia) -> Unit,// 其他参数...
) {// 在onBindViewHolder中holder.itemView.setOnClickListener {onAdClick(ads[position])}
}

7.2 最佳实践总结

1.生命周期管理:所有资源(播放器、图片请求、计时器)必须与生命周期绑定,避免内存泄漏

2.资源优先级:视频加载优先级低于图片,弱网环境下自动降级为图片展示

3.用户体验

  • 首次加载显示占位图
  • 视频默认静音播放,提供手动开启声音按钮
  • 滑动时平滑过渡,避免卡顿

4.测试覆盖

  • 测试不同网络环境(4G/5G/WiFi/ 弱网)
  • 测试不同尺寸设备的适配性
  • 测试视频播放时的内存占用

实现一个高质量的混合媒体轮播需要兼顾功能完整性和性能稳定性。通过本文的方案,开发者可以构建一个支持图片与视频混合展示、自动轮播、生命周期感知的广告组件,同时通过优化策略确保在各种设备上的流畅体验。关键在于合理管理媒体资源,平衡加载速度与内存占用,最终提升用户体验和广告转化效果。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI大模型企业落地指南-笔记01

前言AI技术的发展趋势必然是越来越普及&#xff0c;越来越“技术平权”的。在未来10年内&#xff0c;AI将以各种方式“融入”人类世界&#xff0c;与人类乃至世界深度融合。一. 概念第1章 AI与大模型概述1.1 什么是AI人工智能&#xff08;全称Artificial Intelligence&#xff…

Linux-孤儿进程和僵死进程

文章目录孤儿进程概述僵死进程概述孤儿进程 概述 父进程运行结束&#xff0c;子进程还在运行&#xff0c;此时&#xff0c;子进程就成了孤儿进程&#xff08;Orphan Process&#xff09;每当出现一个孤儿进程的时候&#xff0c;内核就把孤儿进程的父进程设置为 init &#xf…

【Redis 进阶】----主从复制(重点理解流程和原理)

在分布式系统中为了解决单点问题&#xff08;某个服务器程序只有一个节点&#xff08;只搞一个物理服务器来部署这个服务器程序&#xff09;。可用性不高&#xff1a;如果这个机器挂了意味着服务就中断了&#xff1b;性能 / 支持的并发量比较有限&#xff09;。通常会把数据复制…

【Redisson】redis最佳实践-RedissonUtils+Caffeine

RedissonUtils - 企业级 Redis 缓存工具库 - 二级缓存 项目地址: hhttps://gitee.com/chen934298133/redisson-utils问题反馈: Issues邮箱: chen934298133163.com &#x1f4d6; 项目简介 RedissonUtils 是一个基于 Redisson 的企业级 Redis 缓存工具库&#xff0c;提供了完…

QT(QTableWidget)

QT6QTableWidget QTableWidget是一种Item Widget组件&#xff0c;它以表格形式和管理数据&#xff0c;表格的每个单元格关联一个QTableWidgetItem对象&#xff0c;可以设置每个单元格的文字内容、字体、文字颜色、背景色、图标等&#xff0c;还可以有复选框。每个单元格还可以存…

Sentinel相关记录

系列文章目录 draft Sentinel 是阿里巴巴开源的 轻量级服务防护组件&#xff0c;主要用于实现以下功能&#xff1a;流量控制FlowRule&#xff08;Rate Limiting&#xff09;&#xff1a;限制单位时间内的请求量&#xff0c;防止系统过载。 熔断降级DegradeRule&#xff08;Ci…

2025年渗透测试面试题总结-29(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 二百四十一、XSS 设置Http-Only如何绕过 二百四十二、XSS攻击手段分类 二百四十三、高杀软覆盖工作组的渗…

如何用Wireshark捕获当前房间路由器和主机的数据包

一、前期工作 在我的这篇文章中&#xff1a; Wireshark USRP联合波形捕获&#xff08;上&#xff09;-CSDN博客 通过192.168.1.103这个主机ip筛选Wireshark捕获的数据包&#xff0c;认为Source和Direction中至少一个包含192.168.1.103才能代表路由器和主机之间的WiFi信号。 …

深度解析游戏引擎中的相机:视图矩阵

在现代游戏引擎中&#xff0c;相机系统是不可或缺的一部分。它决定了玩家在游戏中看到的视角和场景。而视图矩阵作为相机系统的核心组件之一&#xff0c;起到了至关重要的作用。本文将深入探讨视图矩阵的原理、计算方法及其在游戏引擎中的应用。 视图矩阵的基本概念 视图矩阵…

96、23种设计模式之原型模式(5/23)

原型模式&#xff08;Prototype Pattern&#xff09;是创建型设计模式的一种&#xff0c;其核心思想是通过复制现有对象&#xff08;原型&#xff09;来创建新对象&#xff0c;而非通过构造函数或工厂方法从头构建。该模式将对象的创建过程从构造逻辑转移到复制操作&#xff0c…

【python与生活】如何用Python写一个简单的自动整理文件的脚本?

用 Python 写一个自动整理文件的脚本很简单&#xff0c;核心思路是&#xff1a;按文件后缀&#xff08;如 .jpg、.pdf&#xff09;将文件分类&#xff0c;移动到对应的文件夹&#xff08;如「图片」「文档」&#xff09;中。以下是一个实用的实现方案&#xff0c;新手也能轻松修…

SELinux相关介绍

目录 1.SELinux 概述 2.SELinux 的执行模式 3.SELinux 的使用 1.SELinux 概述 SELinux&#xff08; Security Enhanced Linux 安全性增强的Linux&#xff09;&#xff0c;由美国国家安全局 NSA&#xff08;National Security Agency&#xff09;开发&#xff0c;构建与 Kernel …

【C语言练习】汉诺塔

一、题目 介绍&#xff1a;汉诺塔&#xff08;Tower of Hanoi&#xff09;&#xff0c;又称河内塔&#xff0c;是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子&#xff0c;在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆…

随机森林实战:在鸢尾花数据集上与决策树和逻辑斯蒂回归进行对比

前言 集成学习通过组合多个模型的优势&#xff0c;常能获得比单一模型更优的性能&#xff0c;随机森林便是其中的典型代表。它基于 Bagging 思想&#xff0c;通过对样本和特征的双重随机采样&#xff0c;构建多棵决策树并综合其结果&#xff0c;在降低过拟合风险的同时&#xf…

(计算机网络)TCP 三握中第三次 ACK 丢失会发生什么?

在 TCP 的三次握手过程中&#xff0c;如果 第三次 ACK 丢失&#xff0c;TCP 是如何保证连接可靠建立的呢&#xff1f;1️⃣ 场景说明第三次 ACK&#xff1a;客户端发送给服务器的 ACK&#xff0c;确认服务器的 SYN-ACK。假设该 ACK 在网络传输过程中丢失。2️⃣ 客户端状态客户…

容智Report Agent2.0重磅发布!重新定义企业数据分析AI时代

在数据成为生产要素之一的今天&#xff0c;很多企业依然面临这样的困境&#xff1a; 想要一份年度财务分析&#xff0c;财务团队可能要忙半个月甚至一个月&#xff1b;想查一个业务指标&#xff0c;要先找出在哪个系统&#xff0c;再申请权限、写SQL、调报表&#xff0c;折腾半…

高阶数据结构---ST表

hello大家好&#xff0c;今天是2025年8月23日&#xff0c;我要来给大家分享的是一个高阶数据结构---ST表。 一&#xff1a;引入 1.RMQ问题&#xff1a; 对于一个长度为 n 的序列&#xff0c;有 m 次查询操作&#xff0c;每次查询为一个区间 [l&#xff0c;r] 的最大值&#…

docker 安装nacos(vL2.5.0)

查找nacos 的所需的镜像版本 https://hub.docker.com/r/nacos/nacos-server/tags 拉取你所需的版本&#xff08;我们用v2.5.0&#xff09; docker pull nacos/nacos-server:v2.5.0 注意&#xff1a;因为我们需要挂载外配置文件 直接用volume 挂载目录 缺少初始文件报错 我们…

在github上通过dmca数字版权申诉侵权并删除侵权仓库

DMCA是什么&#xff1f; 《数字千年版权法案》&#xff08;DMCA&#xff09;为版权所有者&#xff08;包括软件开发人员&#xff09;创建了一个标准化的流程&#xff0c;要求GitHub删除侵权内容。您可以在美国版权局的官方网站上找到有关DMCA的更多信息。有关GitHub如何处理DM…

AI安全监控与人才需求的时间悖论(对AI安全模型、AI安全人才需求的一些思考)

当监控者与被监控者都是AI时&#xff0c;谁来监控监控者&#xff1f;这个看似简单的问题&#xff0c;却揭示了人工智能安全领域的根本性困境。一、问题的提出&#xff1a;当AI监控AI 随着大语言模型和生成式AI的快速发展&#xff0c;AI系统在元认知层面的能力越来越强&#xff…