uniapp音乐播放整理

一、前置知识点

1.1 音频组件控制-uni.createInnerAudioContext()

创建并返回内部 audio 上下文 innerAudioContext 对象。

主要用于当前音乐播放;

1.1.1 innerAudioContext属性
属性类型说明只读平台差异说明
srcString音频的数据链接,用于直接播放。微信小程序不支持本地路径
startTimeNumber开始播放的位置(单位:s),默认 0
autoplayBoolean是否自动开始播放,默认 falseH5端部分浏览器不支持
loopBoolean是否循环播放,默认 false
obeyMuteSwitchBoolean是否遵循系统静音开关,当此参数为 false 时,即使用户打开了静音开关,也能继续发出声音,默认值 true微信小程序、百度小程序、抖音小程序、飞书小程序、京东小程序、快手小程序(仅在 iOS 上生效)
durationNumber当前音频的长度(单位:s),只有在当前有合法的 src 时返回,需要在onCanplay中获取
currentTimeNumber当前音频的播放位置(单位:s),只有在当前有合法的 src 时返回,时间不取整,保留小数点后 6 位
pausedBoolean当前是是否暂停或停止状态,true 表示暂停或停止,false 表示正在播放
bufferedNumber音频缓冲的时间点,仅保证当前播放时间点到此时间点内容已缓冲。
volumeNumber音量。范围 0~1。
sessionCategoryString设置音频播放模式,可取值:“ambient” - 不中止其他声音播放,不能后台播放,静音后无声音; “soloAmbient” - 中止其他声音播放,不能后台播放,静音后无声音; “playback” - 中止其他声音,可以后台播放,静音后有声音。 默认值为"playback"。App 3.3.7+
playbackRateNumber播放的倍率。可取值:0.5/0.8/1.0/1.25/1.5/2.0,默认值为1.0App 3.4.5+(Android 需要 6 及以上版本)、微信小程序 2.11.0、支付宝小程序、抖音小程序 2.33.0+、快手小程序、百度小程序 3.120.2+
1.1.2 innerAudioContext方法列表
方法参数说明
play播放(H5端部分浏览器需在用户交互时进行)
pause暂停
stop停止
seekposition跳转到指定位置,单位 s
destroy销毁当前实例
onCanplaycallback音频进入可以播放状态,但不保证后面可以流畅播放
onPlaycallback音频播放事件
onPausecallback音频暂停事件
onStopcallback音频停止事件
onEndedcallback音频自然播放结束事件
onTimeUpdatecallback音频播放进度更新事件
onErrorcallback音频播放错误事件
onWaitingcallback音频加载中事件,当音频因为数据不足,需要停下来加载时会触发
onSeekingcallback音频进行 seek 操作事件
onSeekedcallback音频完成 seek 操作事件
offCanplaycallback取消监听 onCanplay 事件
offPlaycallback取消监听 onPlay 事件
offPausecallback取消监听 onPause 事件
offStopcallback取消监听 onStop 事件
offEndedcallback取消监听 onEnded 事件
offTimeUpdatecallback取消监听 onTimeUpdate 事件
offErrorcallback取消监听 onError 事件
offWaitingcallback取消监听 onWaiting 事件
offSeekingcallback取消监听 onSeeking 事件
offSeekedcallback取消监听 onSeeked 事件
1.1.3 简单示例
// 创建innerAudioContext对象
const innerAudioContext = uni.createInnerAudioContext();
// 开始自动播放
innerAudioContext.autoplay = true;
// 设置音频地址
innerAudioContext.src = 'url.mp3';
// 开始播放的回调函数
innerAudioContext.onPlay(() => {console.log('开始播放');
});
// 播放报错的事件监听
innerAudioContext.onError((res) => {console.log(res.errMsg);console.log(res.errCode);
});

1.2 背景音频控制-uni.getBackgroundAudioManager()

获取全局唯一的背景音频管理器 backgroundAudioManager

主要是实现后台播放功能,退出app或者小程序后还能继续播放,同时状态栏有控制播放状态控件;

1.2.1 backgroundAudioManager属性列表
属性类型说明只读
durationNumber当前音频的长度(单位:s),只有在当前有合法的 src 时返回
currentTimeNumber当前音频的播放位置(单位:s),只有在当前有合法的 src 时返回
pausedBoolean当前是是否暂停或停止状态,true 表示暂停或停止,false 表示正在播放
srcString音频的数据源,默认为空字符串,**当设置了新的 src 时,会自动开始播放,**目前支持的格式有 m4a, aac, mp3, wav
startTimeNumber音频开始播放的位置(单位:s)
bufferedNumber音频缓冲的时间点,仅保证当前播放时间点到此时间点内容已缓冲。
titleString音频标题,用于做原生音频播放器音频标题。原生音频播放器中的分享功能,分享出去的卡片标题,也将使用该值。
epnameString专辑名,原生音频播放器中的分享功能,分享出去的卡片简介,也将使用该值。
singerString歌手名,原生音频播放器中的分享功能,分享出去的卡片简介,也将使用该值。
coverImgUrlString封面图url,用于做原生音频播放器背景图。原生音频播放器中的分享功能,分享出去的卡片配图及背景也将使用该图。
webUrlString页面链接,原生音频播放器中的分享功能,分享出去的卡片简介,也将使用该值。
protocolString音频协议。默认值为 ‘http’,设置 ‘hls’ 可以支持播放 HLS 协议的直播音频,App平台暂不支持
playbackRateNumber播放的倍率。可取值:0.5/0.8/1.0/1.25/1.5/2.0,默认值为1.0。(App 3.4.5+、微信基础库 2.11.0+、支付宝小程序、抖音小程序 2.33.0+、快手小程序、百度小程序 3.120.2+)
1.2.2 backgroundAudioManager方法列表
方法参数说明
play播放
pause暂停
stop停止
seekposition跳转到指定位置,单位 s
onCanplaycallback背景音频进入可以播放状态,但不保证后面可以流畅播放
onPlaycallback背景音频播放事件
onPausecallback背景音频暂停事件
onStopcallback背景音频停止事件
onEndedcallback背景音频自然播放结束事件
onTimeUpdatecallback背景音频播放进度更新事件
onPrevcallback用户在系统音乐播放面板点击上一曲事件(iOS only)
onNextcallback用户在系统音乐播放面板点击下一曲事件(iOS only)
onErrorcallback背景音频播放错误事件
onWaitingcallback音频加载中事件,当音频因为数据不足,需要停下来加载时会触发
1.2.3 简单示例
// 创建bgAudioManager对象
const bgAudioManager = uni.getBackgroundAudioManager();
bgAudioManager.title = '音乐标题';
bgAudioManager.singer = '作者';
bgAudioManager.coverImgUrl = '封面图片';
bgAudioManager.src = 'url.mp3';
// 开始播放的回调函数
bgAudioManager.onPlay(() => {console.log('开始播放');
});
// 播放报错的事件监听
bgAudioManager.onError((res) => {console.log(res.errMsg);console.log(res.errCode);
});
1.2.4 注意点

注意 因为背景音频播放耗费手机电量,所以平台都有管控,需在manifest中填写申请。

  • ios App平台,背景播放需在manifest.json -> app-plus -> distribute -> ios 节点添加 "UIBackgroundModes":["audio"] 才能保证音乐可以后台播放(打包成ipa生效)
  • 小程序平台,需在manifest.json 对应的小程序节点下,填写"requiredBackgroundModes": [“audio”]。发布小程序时平台会审核

二、音乐功能点

2.1 实现效果

  1. 控制播放暂停;
  2. 实现上一首,下一首;
  3. 展示当前音乐当前进度时间,结束时间;展示当前音乐当前进度时间,结束时间;
  4. 可以通过进度条去控制音乐跳转到对应时间点;
  5. 实现倍速播放;
  6. 后台播放;

2.2 获取音乐信息

  1. 当前音乐播放状态;
  2. 音乐列表数据,便于实现上一首下一首;
  3. 当前音乐播放时长,与结束时长,播放速度;
  4. 音乐的地址、封面图片、名称等基础信息;
  5. 歌词展示,到达当前歌词时歌词高亮;

三、实现步骤

3.1 技术选型

通过前置知识点我们了解到了uni.createInnerAudioContext()和uni.getBackgroundAudioManager()的实例属性方法等。

可以根据需求去选择性调用实例,前者可以在小程序中调用来播放音乐;而如果想要退出小程序或者app后依然可以让音乐继续播放,这个时候就可以使用后者来生成悬浮框,以及状态栏中显示;

结论:

  1. 小程序或app中使用uni.createInnerAudioContext();
  2. 退出小程序或app时使用uni.getBackgroundAudioManager();

3.2 实现思路

根据前面整理的音乐所需功能点,我们需要使用store存储一些全局音乐状态信息;便于切换到其他界面的时候可以同步得到最新的音乐信息。

  1. 首先在程序初始化时,实例化一个audio对象挂载到vue原型上;
  2. 用于实时获取当前播放信息;
  3. 初始化时就可以把需要的监听事件挂载,配合实际业务场景;

3.3 简易代码示例

3.3.1 实例化挂载audio对象

入口文件实例化-main.js

// 新建音乐对象挂载到原型上
const innerAudioContext = uni.createInnerAudioContext();
// 音乐播放报错监听
innerAudioContext.onError((res) => {console.log("音乐播放报错监听", res);
});
// 音乐加载中监听
innerAudioContext.onWaiting((res) => {console.log("音乐加载中监听", res);
});
Vue.prototype.$AudioContext = innerAudioContext;
3.3.2 定义一个简单的音乐列表
{
// 滚动条信息
playInfo: {progressWidth: 2, 	// 滚动条currentTime: 0,			// 当前音乐时间scurrentValue: '00:00', // 转换成时间展示duration: 0,				// 当前音乐总时间sdurationValue: '00:00',	// 总时间转换展示 },
// 简易歌曲列表
audioList: [ {title: '未完成之前',src: 'https://music.163.com/song/media/outer/url?id=1453946527.mp3',id: 1453946527,}, {title: '鲜花',src: 'https://music.163.com/song/media/outer/url?id=2086327879.mp3',id: 2086327879,},{title: '水星记',src: 'https://music.163.com/song/media/outer/url?id=441491828.mp3',id: 441491828,}, {title: '人生有时候懂得放弃',src: 'https://music.163.com/song/media/outer/url?id=2139388989.mp3',id: 2139388989,},{title: '精卫',src: 'https://music.163.com/song/media/outer/url?id=1951069525.mp3',id: 1951069525,},
],
}
3.3.3 实现暂停播放、切换音乐

在这里插入图片描述

要实现播放音乐首先要给$AudioContext设置音乐地址src,这样才能通过地址去获取对应的音乐信息。

首选需要在页面一加载时默认配置列表中第一首歌的地址:

onLoad() {this.$AudioContext.playbackRate = 2;if (this.audioList.length) {this.$AudioContext.src = this.audioList[this.currentIndex].src;this.currentTitle = this.audioList[this.currentIndex].title;this.setPlayInfo();}// 开始播放获取音乐信息this.$AudioContext.onPlay((e) => {this.setPlayInfo();});this.$AudioContext.onEnded((e) => {// 结束播放去播放下一首this.hanleAudioChange();});
},

播放按钮: 判断paused的状态选择性去调用播放和暂停方法;

切换音乐: 点击音乐列表行更新音乐地址src,停止当前音乐,最后调用播放方法即可;

// 音乐播放
handlePlay() {this.$AudioContext.paused ? this.$AudioContext.play() : this.$AudioContext.pause();this.paused = this.$AudioContext.paused;this.recursionDeep();
},
// 选择目标音乐播放
handleCurrentAudio(index) {this.currentIndex = index;this.currentTitle = this.audioList[index].title;// 先停止当前音乐this.$AudioContext.stop();// 更换播放地址this.$AudioContext.src = this.audioList[index].src;// 播放音乐this.handlePlay();
},
3.3.4 进度条功能实现

首先明确功能点:

  1. 根据音乐播放进度条增加,显示当前播放时长和总时长(可以根据定时任务获取最新音乐播放信息);
  2. 可以拖动选择特定位置播放(通过touchmove与touchend事件监听实现);
  3. 点击某一位置直接跳转对应位置播放(通过点击事件获取x轴位置)
// 递归循环获取最新音乐进度信息
recursionDeep() {clearTimeout(this.timer);if (this.paused) {return};this.timer = setTimeout(() => {if (!this.isMove) {this.setPlayInfo();this.recursionDeep();}}, 500)
},
// 进度条点击事件
progressClick(event) {const {x} = event.detail;const progressWidth = Math.floor(x / this.progressParentWidth * 100);this.playInfo.progressWidth = progressWidth > 100 ? 100 : progressWidth;console.log("event", event);this.progressMouseDown();
},
// 音乐进度条移动监听
progressMouseMove(event) {if (!this.$AudioContext.src) {return;}this.isMove = true;const {pageX} = event.changedTouches[0];const progressWidth = Math.floor(pageX / this.progressParentWidth * 100);this.playInfo.progressWidth = progressWidth > 100 ? 100 : progressWidth;
},
// 音乐进度条停止监听
progressMouseDown(event) {this.isMove = false;const currentTime = Math.floor(this.$AudioContext.duration * (this.playInfo.progressWidth / 100));this.$AudioContext.seek(currentTime);this.setPlayInfo();if (!this.$AudioContext.paused) {this.$AudioContext.pause();}this.handlePlay();
},

四、完整源码示例

4.1 示例图

在这里插入图片描述

4.2 main.js入口函数

import App from './App'import Vue from 'vue'
import './uni.promisify.adaptor'
Vue.config.productionTip = false
App.mpType = 'app'// 新建音乐对象挂载到原型上
const innerAudioContext = uni.createInnerAudioContext();
// 音乐播放报错监听
innerAudioContext.onError((res) => {console.log("音乐播放报错监听", res);
});
// 音乐加载中监听
innerAudioContext.onWaiting((res) => {console.log("音乐加载中监听", res);
});
Vue.prototype.$AudioContext = innerAudioContext;const app = new Vue({...App
})
app.$mount()

4.3 index.vue界面

<template><view class="content"><scroll-view class="main-container" scroll-y><view class="line_box" :class="currentIndex === index ? 'line_box bgc_line' : 'line_box'"v-for="(item, index) in audioList" :key="item.id" @click="handleCurrentAudio(index)">{{item.title}}</view></scroll-view><view class="audio_box"><view class="current_title" v-show="currentTitle">当前播放歌曲:{{currentTitle}}</view><view class="music-progress-bar" @click="progressClick"><view class="progress-bar-line" :style="{width: playInfo.progressWidth + '%'}" @touchmove="progressMouseMove"@touchend="progressMouseDown"></view></view><view class="show_time"><view>{{playInfo.currentValue}}</view><view>{{playInfo.durationValue}}</view></view><view class="audio_control"><view @click="hanleAudioChange('pre')">上一首</view><view @click="handlePlay">{{ paused ? '播放' : '暂停'}}</view><view @click="hanleAudioChange('next')">下一首</view></view></view></view>
</template><script>export default {data() {return {timer: null,currentTitle: '未完成之前',currentIndex: 0,paused: true,isMove: false,playInfo: {progressWidth: 2, // 滚动条currentTime: 0, // 当前音乐时间scurrentValue: '00:00', // 转换成时间展示duration: 0, // 当前音乐总时间sdurationValue: '00:00', // 总时间转换展示 },audioList: [{title: '未完成之前',src: 'https://music.163.com/song/media/outer/url?id=1453946527.mp3',id: 1453946527,},{title: '鲜花',src: 'https://music.163.com/song/media/outer/url?id=2086327879.mp3',id: 2086327879,},{title: '水星记',src: 'https://music.163.com/song/media/outer/url?id=441491828.mp3',id: 441491828,},{title: '人生有时候懂得放弃',src: 'https://music.163.com/song/media/outer/url?id=2139388989.mp3',id: 2139388989,},{title: '精卫',src: 'https://music.163.com/song/media/outer/url?id=1951069525.mp3',id: 1951069525,},],progressParentWidth: 0,}},onLoad() {this.$AudioContext.playbackRate = 2;if (this.audioList.length) {this.$AudioContext.src = this.audioList[this.currentIndex].src;this.currentTitle = this.audioList[this.currentIndex].title;this.setPlayInfo();}this.$AudioContext.onPlay((e) => {// 开始播放获取音乐信息this.setPlayInfo();});this.$AudioContext.onEnded((e) => {// 结束播放去播放下一首this.hanleAudioChange();});},onShow() {this.$nextTick(async () => {const query = uni.createSelectorQuery().in(this);query.select('.music-progress-bar').boundingClientRect(data => {this.progressParentWidth = data ? Math.floor(data.width) : 0;}).exec();});},onUnload() {// 卸载时关闭监听this.$AudioContext.offPlay();this.$AudioContext.offPlay();},methods: {// 进度条点击事件progressClick(event) {const {x} = event.detail;const progressWidth = Math.floor(x / this.progressParentWidth * 100);this.playInfo.progressWidth = progressWidth > 100 ? 100 : progressWidth;console.log("event", event);this.progressMouseDown();},// 音乐进度条移动监听progressMouseMove(event) {if (!this.$AudioContext.src) {return;}this.isMove = true;const {pageX} = event.changedTouches[0];const progressWidth = Math.floor(pageX / this.progressParentWidth * 100);this.playInfo.progressWidth = progressWidth > 100 ? 100 : progressWidth;},// 音乐进度条停止监听progressMouseDown(event) {this.isMove = false;const currentTime = Math.floor(this.$AudioContext.duration * (this.playInfo.progressWidth / 100));this.$AudioContext.seek(currentTime);this.setPlayInfo();if (!this.$AudioContext.paused) {this.$AudioContext.pause();}this.handlePlay();},// 音乐播放handlePlay() {this.$AudioContext.paused ? this.$AudioContext.play() : this.$AudioContext.pause();this.paused = this.$AudioContext.paused;this.recursionDeep();},// 选择目标音乐播放handleCurrentAudio(index) {this.currentIndex = index;this.currentTitle = this.audioList[index].title;// 先停止当前音乐this.$AudioContext.stop();// 更换播放地址this.$AudioContext.src = this.audioList[index].src;// 播放音乐this.handlePlay();},// 递归循环获取最新音乐进度信息recursionDeep() {clearTimeout(this.timer);if (this.paused) {return};this.timer = setTimeout(() => {if (!this.isMove) {this.setPlayInfo();this.recursionDeep();}}, 500)},// 秒转换为分钟secondsToMinutesWithSeconds(seconds) {const minutes = Math.floor(seconds / 60);const remainingSeconds = Math.floor(seconds % 60);return `${this.padZero(minutes)}:${this.padZero(remainingSeconds)}`;},// 补零padZero(number, length = 2) {var str = "" + number;while (str.length < length) {str = "0" + str;}return str;},// 设置播放对象setPlayInfo() {const currentTime = this.$AudioContext.currentTime || 0;const duration = this.$AudioContext.duration || 0;const progressWidth = duration === 0 ? '2' : Math.floor((currentTime / duration) * 100);const currentValue = this.secondsToMinutesWithSeconds(currentTime);const durationValue = this.secondsToMinutesWithSeconds(duration);this.playInfo = {currentTime,duration,progressWidth,currentValue,durationValue};},// 切换歌曲hanleAudioChange(type = 'next') {if (type === 'pre') {this.currentIndex = this.currentIndex === 0 ? this.audioList.length - 1 : this.currentIndex - 1;} else {this.currentIndex = this.currentIndex === this.audioList.length - 1 ? 0 : this.currentIndex + 1;};this.$AudioContext.src = this.audioList[this.currentIndex].src;this.currentTitle = this.audioList[this.currentIndex].title;// 播放歌曲this.handlePlay();},}}
</script><style>.content {width: 100vw;height: calc(100vh - 44px - env(safe-area-inset-top));background-color: #1A262D;color: #fff;}.main-container {width: 100vw;height: 46vh;}.line_box {display: flex;align-items: center;justify-content: center;width: 92%;height: 60px;border-radius: 8px;margin: 10px auto;border: 2px solid #eee;background-color: aquamarine;color: #333;font-weight: bold;}.audio_control {display: flex;align-items: center;justify-content: space-around;color: #333;margin-top: 40px;}.audio_control view {width: 100px;height: 40px;text-align: center;line-height: 40px;background: #edeeab;border: 1px solid #eee;border-radius: 6px;}.audio_box {width: 90%;margin: 30px auto;}.current_title {margin-bottom: 20px;font-weight: bold;font-size: 18px;}.bgc_line {background-color: #e1964b;}.show_time {width: 100%;display: flex;justify-content: space-between;margin-top: 12rpx;}// 音乐进度条.music-progress-bar {position: relative;width: 100%;height: 6rpx;border-radius: 6rpx;background-color: #f3e7d9;.progress-bar-line {position: absolute;top: 0%;left: 0%;width: 2%;height: 100%;border-radius: 6rpx;background-color: #e1964b;}.progress-bar-line::after {content: "";display: inline-block;position: absolute;right: 0%;top: 50%;transform: translateY(-50%);width: 20rpx;height: 20rpx;background-color: #fff;border-radius: 50%;}}
</style>

4.4 项目源码地址

https://gitee.com/yangdacongming/implementation-of-uniapp-music.git

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

聚观早报 | 乐道L60实车曝光;《萤火突击》公测定档

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 5月11日消息 乐道L60实车曝光 《萤火突击》公测定档 华为官网更新管理层信息 OPPO Reno12 Pro细节曝光 三星电子…

瀚高数据库(HighGoDB)Windows安装使用

1.下载 2.安装 瀚高数据库下载与安装&#xff08;Windows版&#xff09;-CSDN博客 3.连接工具 4.建库、建表操作 瀚高数据库管理工具-CSDN博客 *报错Cant access non-default database&#xff0c;需要右键数据库-设为活动对象 5.导入外部数据&#xff08;迁移、对比&…

Stable Diffusion写真完整教程

前言 最近自己对AI非常痴迷&#xff0c;并且今后也会一直在这个领域深耕&#xff0c;所以就想着先入门&#xff0c;因此花时间研究了一番&#xff0c;还好&#xff0c;出了点小成果&#xff0c;接下来给大家汇报一下。 AI绘画 提到AI绘画&#xff0c;大家可能立马会想到made…

住宅IP代理和数据中心/机房IP代理之间的区别

一、什么是数据中心/机房IP代理&#xff1f; 数据中心/机房IP代理是使用数据中心拥有并进行分配和管理的IP的代理&#xff0c;俗称机房IP代理。 二、数据中心/机房IP代理的特点 与住宅代理通过使用ISP拥有和分配的IP地址的设备路由请求的情况不同&#xff0c;数据中心代理利…

品鉴中的挑战与探索:如何勇敢尝试不同类型的云仓酒庄雷盛红酒

品鉴云仓酒庄雷盛红酒不仅是一种感官的享受&#xff0c;更是一种挑战与探索的过程。不同类型的云仓酒庄雷盛红酒具有各自与众不同的风味和特点&#xff0c;通过勇敢尝试不同类型的红酒&#xff0c;我们可以拓展自己的品鉴视野&#xff0c;发现更多未知的美妙滋味。 首先&#x…

postgresql中写python去读取HDFS数据,像表一样使用。

简介 首先postgresql是支持python的&#xff0c;在安装postgresql数据库的时候需要执行python支持。可以使用python进行写fundcation 自然也就可以自定义funcation去读取HDFS文件&#xff0c;以此替换掉hive的&#xff0c;省去中间频繁切换服务器的麻烦。 安装postgresql use…

SpringBoot+Vue实现图片滑块和文字点击验证码

一、背景 1.1 概述 传统字符型验证码展示-填写字符-比对答案的流程&#xff0c;目前已可被机器暴力破解&#xff0c;应用程序容易被自动化脚本和机器人攻击。 摒弃传统字符型验证码&#xff0c;采用行为验证码采用嵌入式集成方式&#xff0c;接入方便&#xff0c;安全&#…

【Android】Kotlin学习之Kotlin方法的声明和传参

方法声明 普通类的方法 静态类的方法 不需要构建实例对象, 可以通过类名直接访问静态方法 : NumUtil.double(1) companion object 伴生类的方法 使用companion object 在普通类里定义静态方法 参数 括号内传入方法 : 当参数是方法时, 并且是最后一个参数 , 可以使用括号外…

有什么实用的还原试卷的app免费?6个软件教你快速进行还原试卷

有什么实用的还原试卷的app免费&#xff1f;6个软件教你快速进行还原试卷 在现代化的教学环境中&#xff0c;使用数字化工具进行试卷还原变得愈发重要。以下是六个实用的、免费的应用程序&#xff0c;它们为还原试卷提供了便捷的解决方案。 FunAI&#xff1a; 这款应用程序可…

【JVM】ASM开发

认识ASM ASM是一个Java字节码操纵框架&#xff0c;它能被用来动态生成类或者增强既有类的功能。 ASM可以直接产生二进制class文件&#xff0c;也可以在类被加载入虚拟机之前动态改变类行为&#xff0c;ASM从类文件中读入信息后能够改变类行为&#xff0c;分析类信息&#xff…

中仕公考:怎么看岗位是否有编制?

1、看公告标题 有编&#xff1a;公告标题中含有编内、xx地区事业单位招聘、xx教育系统招聘……等关键词&#xff0c;这样的公告是有编制的。 无编&#xff1a;公告标题含有编外、非在编、临聘、劳务派遣、政府购买岗位……等关键词&#xff0c;说明是没有编制的 2、看公告引导…

算法基础01一快速排序,归并排序,二分

一.排序 1.快速 排序 基于分治 确定分界点 左 右 中间 随机划分区间 左半边<x >x在右半边递归处理左右两端 #include<iostream>using namespace std;const int N 1e6 10;int n; int q[N]; void quick_sort(int q[],int l,int r) {if(l>r)return;//边界&…

表格内容高效拆分,自定义行数随心所欲,让数据处理更高效!

在信息化社会的今天&#xff0c;表格成为了我们处理数据、整理信息的重要工具。然而&#xff0c;当表格内容过于庞大时&#xff0c;如何高效地拆分表格内容成为了摆在我们面前的一大难题。传统的拆分方法往往耗时耗力&#xff0c;且难以满足我们个性化的需求。 首先&#xff0…

【JAVA进阶篇教学】第十三篇:Java中volatile关键字讲解

博主打算从0-1讲解下java进阶篇教学&#xff0c;今天教学第十三篇&#xff1a;volatile关键字讲解。 在 Java 中&#xff0c;volatile关键字是一种轻量级的同步机制&#xff0c;用于确保变量的可见性和禁止指令重排序。本文将详细解释volatile关键字的工作原理、可见性保证以及…

Goland GC

Goland GC 引用Go 1.3 mark and sweep 标记法Go 1.5 三色标记法屏障机制插入屏障删除写屏障总结 Go 1.8 混合写屏障(hybrid write barrier)机制总结 引用 https://zhuanlan.zhihu.com/p/675127867 Garbage Collection&#xff0c;缩写为GC&#xff0c;一种内存管理回收的机制…

MyBatis-plus(一):快速入门

目录 一、MyBatis-plus 快速入门 1、原理 2、实体类命名规则 3、常见注解 4、主键 id 策略 5、使用 TableField 的常见场景 6、常用配置 二、核心功能 1、条件构造器 2、自定义 SQL 3、IService 接口 一、MyBatis-plus 快速入门 1、原理 MyBatisPlus 通过扫描实体…

如何使用联合体判断一个机器是大端还是小端

如何使用联合体判断一个机器是大端还是小端 #include<iostream> using namespace std; union Checker//联合体中的数据共享内存 {int val;char ch[2]; }; int main() {Checker checker;checker.val 0x1234;if (checker.ch[0] 0x34)//数组中的数据是由低地址往高地址存放…

CCC数字钥匙各版本关系

CCC钥匙规范版本关系 CCC数字钥匙架构Overview

BGP(border gateway protocol)边界网关协议初识篇

BGP它是一种路径矢量协议&#xff0c;用于决定数据包在互联网中的最佳路径。 1、工作原理&#xff1a; 自治系统&#xff08;AS&#xff09;间路由: BGP主要用于连接不同自治系统之间的路由器&#xff0c;其中每个自治系统&#xff08;AS&#xff09;代表一组具有共同路由的网…

AJ65SBT2B-64DA 三菱CC-Link D/A转换模块

AJ65SBT2B-64DA 是将数字值(16位有符号BIN数据)转换为模拟值(电压或电流)的模块。 AJ65SBT2B-64DA参数说明&#xff1a;4通道&#xff1b;输入分辨率0~12000&#xff0c;-12000~12000&#xff0c;-16000~16000&#xff1b;输出DC-10~10V&#xff0c;DC0~20mA&#xff1b;转换速…