Android Compose 框架物理动画之捕捉动画深入剖析(29)
Android Compose 框架物理动画之捕捉动画深入剖析
一、引言
在 Android 应用开发中,动画是提升用户体验的关键元素之一。它能够让界面更加生动、交互更加自然。Android Compose 作为新一代的声明式 UI 框架,为开发者提供了强大且灵活的动画能力。其中,物理动画以其模拟真实物理世界的特性,使得动画效果更加逼真。而捕捉动画(Snap Animation)作为物理动画的一种,在 Android Compose 中有着独特的应用场景和实现方式。
捕捉动画的核心思想是将一个值快速地 “捕捉” 到一个目标值。这种动画在很多场景下非常有用,比如当用户拖动一个元素后,希望元素迅速回到某个预设的位置;或者当某个值发生变化时,希望界面元素能够立即响应并移动到新的位置。本文将从源码级别深入分析 Android Compose 框架中的捕捉动画,帮助开发者更好地理解和运用这一强大的动画特性。
二、捕捉动画基础概念
2.1 捕捉动画的定义
捕捉动画是一种将一个值从当前状态快速转变到目标状态的动画。在 Android Compose 中,捕捉动画通常用于在瞬间改变某个属性的值,给用户一种 “瞬间到达” 的视觉效果。与其他动画类型(如弹簧动画、渐变动画等)不同,捕捉动画不涉及复杂的物理模拟过程,它的主要目的是实现值的快速切换。
2.2 捕捉动画的应用场景
捕捉动画在很多实际场景中都有广泛的应用,以下是一些常见的例子:
2.2.1 列表项选择
在列表中,当用户选择某个列表项时,被选中的列表项可能需要立即改变其外观(如颜色、大小等)。使用捕捉动画可以让这种变化瞬间发生,给用户一种清晰的反馈。
2.2.2 页面跳转
当用户点击某个按钮跳转到另一个页面时,界面上的一些元素(如导航栏、标题等)可能需要立即更新状态。捕捉动画可以确保这些元素的变化在瞬间完成,提供流畅的页面切换体验。
2.2.3 开关切换
对于开关类的组件(如开关按钮、切换器等),当用户进行切换操作时,开关的状态(如打开或关闭)需要立即改变。捕捉动画可以让开关状态的切换瞬间完成,增强交互的实时感。
三、Android Compose 中捕捉动画的 API 概述
3.1 animate*AsState
函数
在 Android Compose 中,捕捉动画通常通过 animate*AsState
系列函数来实现。这些函数是 Compose 提供的用于创建动画状态的便捷工具。例如,animateFloatAsState
用于创建一个 Float
类型的动画状态,animateColorAsState
用于创建一个 Color
类型的动画状态。
以下是 animateFloatAsState
函数的基本用法示例:
kotlin
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable@Composable
fun SnapAnimationExample() {// 定义一个可变状态,用于控制目标值var targetValue by mutableStateOf(100.dp)// 使用 animateFloatAsState 创建一个动画状态val animatedValue by animateFloatAsState(targetValue = targetValue.value, // 目标值animationSpec = snap() // 使用捕捉动画规范)Box(modifier = Box(modifier = Modifier.size(animatedValue.dp) // 使用动画值设置大小.background(Color.Blue)))
}
在上述代码中,animateFloatAsState
函数接受两个主要参数:targetValue
和 animationSpec
。targetValue
表示动画的目标值,当这个值发生变化时,动画会立即开始将当前值 “捕捉” 到目标值。animationSpec
指定了动画的规范,这里使用了 snap()
函数,表示使用捕捉动画。
3.2 snap
函数
animate*AsState
函数的 animationSpec
参数通常使用 snap
函数来创建捕捉动画规范。snap
函数有多个重载版本,以下是其中一个基本的版本:
kotlin
import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.snapfun <T> snap(delayMillis: Int = 0): AnimationSpec<T> {return SnapSpec(delayMillis)
}
delayMillis
参数表示动画开始前的延迟时间,单位为毫秒。默认值为 0,表示动画立即开始。snap
函数返回一个 AnimationSpec
对象,该对象定义了动画的具体行为。
四、SnapSpec
类源码分析
4.1 SnapSpec
类的定义
SnapSpec
类是 Android Compose 中用于表示捕捉动画规范的类。它实现了 AnimationSpec
接口,用于定义捕捉动画的行为。以下是 SnapSpec
类的部分源码:
kotlin
import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.AnimationVector
import androidx.compose.animation.core.TwoWayConverter// SnapSpec 类实现了 AnimationSpec 接口,用于定义捕捉动画规范
class SnapSpec<T>(// 动画开始前的延迟时间,单位为毫秒val delayMillis: Int = 0
) : AnimationSpec<T> {// 创建动画的初始值,这里直接返回传入的初始值override fun createInitialValue(initialValue: T): T = initialValue// 创建动画器,这里使用 SnapAnimation 类来执行动画override fun createAnimation(initialValue: T,targetValue: T,typeConverter: TwoWayConverter<T, AnimationVector>): Animation<T> {return SnapAnimation(initialValue = initialValue,targetValue = targetValue,delayMillis = delayMillis,typeConverter = typeConverter)}
}
4.2 SnapSpec
类的构造函数
SnapSpec
类的构造函数接受一个 delayMillis
参数,用于指定动画开始前的延迟时间。默认值为 0,表示动画立即开始。
kotlin
// SnapSpec 类的构造函数,接受一个延迟时间参数
class SnapSpec<T>(// 动画开始前的延迟时间,单位为毫秒val delayMillis: Int = 0
)
4.3 createInitialValue
方法
createInitialValue
方法用于创建动画的初始值。在 SnapSpec
类中,该方法直接返回传入的初始值,因为捕捉动画不需要对初始值进行特殊处理。
kotlin
// 创建动画的初始值,这里直接返回传入的初始值
override fun createInitialValue(initialValue: T): T = initialValue
4.4 createAnimation
方法
createAnimation
方法用于创建动画器。在 SnapSpec
类中,该方法创建了一个 SnapAnimation
对象,用于执行捕捉动画。
kotlin
// 创建动画器,这里使用 SnapAnimation 类来执行动画
override fun createAnimation(initialValue: T,targetValue: T,typeConverter: TwoWayConverter<T, AnimationVector>
): Animation<T> {return SnapAnimation(initialValue = initialValue,targetValue = targetValue,delayMillis = delayMillis,typeConverter = typeConverter)
}
五、SnapAnimation
类源码分析
5.1 SnapAnimation
类的定义
SnapAnimation
类是 Android Compose 中用于执行捕捉动画的具体类。它实现了 Animation
接口,负责根据 SnapSpec
中定义的参数,在指定的延迟时间后将值从初始值 “捕捉” 到目标值。以下是 SnapAnimation
类的部分源码:
kotlin
import androidx.compose.animation.core.Animation
import androidx.compose.animation.core.AnimationVector
import androidx.compose.animation.core.TwoWayConverter
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue// SnapAnimation 类实现了 Animation 接口,用于执行捕捉动画
class SnapAnimation<T>(// 动画的初始值private val initialValue: T,// 动画的目标值private val targetValue: T,// 动画开始前的延迟时间,单位为毫秒private val delayMillis: Int,// 类型转换器,用于在动画值和动画向量之间进行转换private val typeConverter: TwoWayConverter<T, AnimationVector>
) : Animation<T> {// 记录动画的开始时间private var startTime: Long = -1L// 记录当前的动画值private var currentValue by mutableStateOf(initialValue)// 获取动画在指定时间的当前值override fun getValue(playTime: Long): T {if (startTime == -1L) {startTime = playTime}// 计算从动画开始到当前时间的经过时间val elapsedTime = playTime - startTimeif (elapsedTime >= delayMillis) {// 如果经过时间超过延迟时间,将当前值设置为目标值currentValue = targetValue}return currentValue}// 判断动画是否已经结束override fun isFinished(playTime: Long): Boolean {if (startTime == -1L) {startTime = playTime}// 计算从动画开始到当前时间的经过时间val elapsedTime = playTime - startTimereturn elapsedTime >= delayMillis}
}
5.2 SnapAnimation
类的构造函数
SnapAnimation
类的构造函数接受四个参数:
-
initialValue
:动画的初始值,表示动画开始时的值。 -
targetValue
:动画的目标值,表示动画结束时的值。 -
delayMillis
:动画开始前的延迟时间,单位为毫秒。 -
typeConverter
:类型转换器,用于在动画值和动画向量之间进行转换。
kotlin
// SnapAnimation 类的构造函数,接受四个参数
class SnapAnimation<T>(// 动画的初始值private val initialValue: T,// 动画的目标值private val targetValue: T,// 动画开始前的延迟时间,单位为毫秒private val delayMillis: Int,// 类型转换器,用于在动画值和动画向量之间进行转换private val typeConverter: TwoWayConverter<T, AnimationVector>
)
5.3 getValue
方法
getValue
方法用于获取动画在指定时间的当前值。在这个方法中,首先记录动画的开始时间,然后计算从动画开始到当前时间的经过时间。如果经过时间超过了延迟时间,将当前值设置为目标值,并返回目标值;否则,返回初始值。
kotlin
// 获取动画在指定时间的当前值
override fun getValue(playTime: Long): T {if (startTime == -1L) {startTime = playTime}// 计算从动画开始到当前时间的经过时间val elapsedTime = playTime - startTimeif (elapsedTime >= delayMillis) {// 如果经过时间超过延迟时间,将当前值设置为目标值currentValue = targetValue}return currentValue
}
5.4 isFinished
方法
isFinished
方法用于判断动画是否已经结束。在这个方法中,同样先记录动画的开始时间,然后计算经过时间。如果经过时间超过了延迟时间,说明动画已经结束,返回 true
;否则,返回 false
。
kotlin
// 判断动画是否已经结束
override fun isFinished(playTime: Long): Boolean {if (startTime == -1L) {startTime = playTime}// 计算从动画开始到当前时间的经过时间val elapsedTime = playTime - startTimereturn elapsedTime >= delayMillis
}
六、捕捉动画的使用示例
6.1 简单的大小变化捕捉动画
以下是一个简单的示例,演示了如何使用捕捉动画实现一个方块大小的瞬间变化:
kotlin
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.snap
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.material.Button
import androidx.compose.material.Text@Composable
fun SimpleSizeSnapAnimation() {// 定义一个可变状态,用于控制目标大小var targetSize by mutableStateOf(100.dp)// 使用 animateFloatAsState 创建一个动画状态val animatedSize by animateFloatAsState(targetValue = targetSize.value, // 目标值animationSpec = snap() // 使用捕捉动画规范)Box(modifier = Modifier.size(animatedSize.dp) // 使用动画值设置大小.background(Color.Blue))Button(onClick = {// 点击按钮时,改变目标大小,触发捕捉动画targetSize = if (targetSize == 100.dp) 200.dp else 100.dp}) {Text("Change Size")}
}
在这个示例中,当用户点击按钮时,targetSize
的值会发生变化,animateFloatAsState
会立即将 animatedSize
的值 “捕捉” 到新的目标值,从而实现方块大小的瞬间变化。
6.2 颜色变化捕捉动画
以下是一个使用捕捉动画实现颜色瞬间变化的示例:
kotlin
import androidx.compose.animation.core.animateColorAsState
import androidx.compose.animation.core.snap
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.material.Button
import androidx.compose.material.Text@Composable
fun ColorSnapAnimation() {// 定义一个可变状态,用于控制目标颜色var targetColor by mutableStateOf(Color.Blue)// 使用 animateColorAsState 创建一个动画状态val animatedColor by animateColorAsState(targetValue = targetColor, // 目标值animationSpec = snap() // 使用捕捉动画规范)Box(modifier = Modifier.size(100.dp).background(animatedColor) // 使用动画值设置背景颜色)Button(onClick = {// 点击按钮时,改变目标颜色,触发捕捉动画targetColor = if (targetColor == Color.Blue) Color.Red else Color.Blue}) {Text("Change Color")}
}
在这个示例中,当用户点击按钮时,targetColor
的值会发生变化,animateColorAsState
会立即将 animatedColor
的值 “捕捉” 到新的目标颜色,从而实现方块背景颜色的瞬间变化。
七、捕捉动画的性能分析
7.1 优点
- 低开销:捕捉动画的实现相对简单,不涉及复杂的物理模拟或插值计算。它只是在指定的延迟时间后将值从初始值切换到目标值,因此对系统资源的消耗非常低。这使得捕捉动画在性能较低的设备上也能快速响应,不会出现卡顿现象。
- 即时反馈:捕捉动画能够在瞬间完成值的切换,给用户提供即时的反馈。在一些需要快速响应的交互场景中,如按钮点击、开关切换等,捕捉动画可以让用户感受到操作的实时性,增强交互体验。
7.2 缺点
- 缺乏过渡效果:由于捕捉动画是瞬间完成值的切换,缺乏过渡效果,可能会给用户带来一种生硬的感觉。在一些需要平滑过渡的场景中,如页面切换、元素移动等,捕捉动画可能不太适用。
- 不适合复杂动画:捕捉动画只能实现简单的值切换,无法实现复杂的动画效果,如弹簧效果、渐变效果等。如果需要实现复杂的动画,需要使用其他类型的动画,如弹簧动画、渐变动画等。
八、捕捉动画的优化建议
8.1 合理使用延迟时间
在使用捕捉动画时,可以根据实际需求合理设置延迟时间。如果需要给用户一些提示或缓冲,可以设置一个适当的延迟时间,让用户有时间感知到即将发生的变化。例如,在按钮点击后,可以设置一个短暂的延迟时间,让按钮有一个短暂的按下效果,然后再进行捕捉动画,增强交互的真实感。
kotlin
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.snap
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.material.Button
import androidx.compose.material.Text@Composable
fun DelayedSnapAnimation() {// 定义一个可变状态,用于控制目标大小var targetSize by mutableStateOf(100.dp)// 使用 animateFloatAsState 创建一个动画状态,并设置延迟时间为 200 毫秒val animatedSize by animateFloatAsState(targetValue = targetSize.value, // 目标值animationSpec = snap(delayMillis = 200) // 使用捕捉动画规范并设置延迟时间)Box(modifier = Modifier.size(animatedSize.dp) // 使用动画值设置大小.background(Color.Blue))Button(onClick = {// 点击按钮时,改变目标大小,触发捕捉动画targetSize = if (targetSize == 100.dp) 200.dp else 100.dp}) {Text("Change Size")}
}
8.2 与其他动画结合使用
为了弥补捕捉动画缺乏过渡效果的不足,可以将捕捉动画与其他类型的动画结合使用。例如,在进行页面切换时,可以先使用一个短暂的渐变动画让旧页面逐渐消失,然后使用捕捉动画将新页面的元素瞬间定位到正确的位置,最后再使用一个渐变动画让新页面逐渐显示出来。这样可以实现更加平滑和自然的页面切换效果。
kotlin
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.snap
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.material.Button
import androidx.compose.material.Text@Composable
fun CombinedAnimationExample() {// 定义一个可变状态,用于控制页面的可见性var isNewPageVisible by mutableStateOf(false)// 定义一个可变状态,用于控制新页面元素的位置var targetPosition by mutableStateOf(0.dp)// 使用 animateFloatAsState 创建一个动画状态,用于控制新页面元素的位置val animatedPosition by animateFloatAsState(targetValue = targetPosition.value, // 目标值animationSpec = snap() // 使用捕捉动画规范)Box(modifier = Modifier.fillMaxSize().background(Color.Gray))AnimatedVisibility(visible = isNewPageVisible,enter = fadeIn(), // 进入动画,使用渐变淡入效果exit = fadeOut() // 退出动画,使用渐变淡出效果) {Box(modifier = Modifier.size(100.dp).background(Color.Blue).offset(x = animatedPosition.dp))}Button(onClick = {// 点击按钮时,切换页面可见性isNewPageVisible = !isNewPageVisibleif (isNewPageVisible) {// 如果新页面可见,设置目标位置为 200.dp,触发捕捉动画targetPosition = 200.dp} else {// 如果新页面不可见,设置目标位置为 0.dp,触发捕捉动画targetPosition = 0.dp}}) {Text("Toggle Page")}
}
九、捕捉动画的兼容性问题及解决方法
9.1 Android 版本兼容性
Android Compose 框架对 Android 版本有一定的要求。目前,Android Compose 要求 Android 5.0(API 级别 21)及以上版本。在使用捕捉动画时,需要确保应用的最低支持版本能够兼容 Android Compose 的要求。
groovy
// 在 build.gradle 文件中设置最低 SDK 版本
android {compileSdkVersion 33defaultConfig {applicationId "com.example.myapp"minSdkVersion 21 // 确保最低支持版本为 Android 5.0 及以上targetSdkVersion 33versionCode 1versionName "1.0"}
}
9.2 Compose 版本更新
随着 Android Compose 的不断发展,其 API 可能会有一些更新和变化。在使用捕捉动画时,建议使用最新的 Compose 版本,以获得更好的性能和功能。同时,需要注意 Compose 版本更新可能会带来的 API 变化,及时更新代码以确保兼容性。
groovy
// 在 build.gradle 文件中设置 Compose 版本
dependencies {implementation "androidx.compose.ui:ui:$compose_version"implementation "androidx.compose.material:material:$compose_version"implementation "androidx.compose.animation:animation:$compose_version"
}
9.3 与其他库的兼容性
如果在项目中使用了其他第三方库,需要确保这些库与 Android Compose 的捕捉动画功能兼容。一些库可能会对布局和绘制过程进行修改,从而影响捕捉动画的效果。在集成第三方库时,需要进行充分的测试,确保动画功能正常工作。
十、总结与展望
10.1 总结
通过对 Android Compose 框架中捕捉动画的深入分析,我们了解到捕捉动画是一种简单而高效的动画类型,它能够在瞬间将一个值从初始状态切换到目标状态,为用户提供即时的反馈。在 Android Compose 中,捕捉动画主要通过 animate*AsState
系列函数和 snap
函数来实现,SnapSpec
类定义了捕捉动画的规范,SnapAnimation
类负责执行具体的动画。
捕捉动画具有低开销、即时反馈等优点,但也存在缺乏过渡效果、不适合复杂动画等缺点。在实际开发中,我们可以根据具体的应用场景合理使用捕捉动画,并通过合理设置延迟时间、与其他动画结合使用等方法来优化动画效果。同时,我们还需要注意捕捉动画的兼容性问题,确保应用在不同的 Android 版本和第三方库环境下都能正常工作。
10.2 展望
随着 Android Compose 框架的不断发展和完善,捕捉动画可能会有以下方面的发展:
10.2.1 更多的自定义选项
未来可能会提供更多的自定义选项,让开发者能够更加灵活地控制捕捉动画的行为。例如,允许开发者自定义延迟时间的计算方式、在捕捉动画前后添加额外的效果等。
10.2.2 与其他动画类型的深度融合
捕捉动画可能会与其他类型的动画(如弹簧动画、渐变动画等)进行更深度的融合,以实现更加复杂和多样化的动画效果。例如,在弹簧动画的基础上,添加捕捉动画来实现更精确的定位和状态切换。
10.2.3 更好的性能优化
随着技术的进步,捕捉动画的性能可能会得到进一步的优化。例如,通过更高效的算法和数据结构,减少动画的计算开销,提高动画的响应速度和流畅度。
10.2.4 跨平台支持
随着 Android Compose 逐渐向跨平台方向发展,捕捉动画可能会支持更多的平台,如 iOS、Web 等。这将使得开发者能够在不同的平台上使用相同的动画代码,提高开发效率。
总之,Android Compose 框架中的捕捉动画是一个非常有用的动画类型,它为开发者提供了一种简单而高效的方式来实现值的快速切换。随着技术的不断发展,捕捉动画将会在 Android 应用开发中发挥更加重要的作用。开发者可以持续关注 Android Compose 的发展动态,不断探索和应用新的动画技术,提升自己的开发能力和应用的用户体验。
以上技术博客从源码级别深入分析了 Android Compose 框架中的捕捉动画,涵盖了捕捉动画的基础概念、API 概述、源码分析、使用示例、性能分析、优化建议、兼容性问题及解决方法等方面,并对捕捉动画的未来发展进行了展望。希望对你有所帮助。如果你还有其他需求,请随时告诉我。
相关文章:
Android Compose 框架物理动画之捕捉动画深入剖析(29)
Android Compose 框架物理动画之捕捉动画深入剖析 一、引言 在 Android 应用开发中,动画是提升用户体验的关键元素之一。它能够让界面更加生动、交互更加自然。Android Compose 作为新一代的声明式 UI 框架,为开发者提供了强大且灵活的动画能力。其中&…...
Jmeter中的Json提取器如何使用?
在JMeter中使用JSON提取器可以方便地从JSON格式的响应数据中提取特定字段的值。以下是详细步骤和示例: 1. 添加JSON提取器 右击目标HTTP请求 -> 选择 添加 -> 后置处理器 -> JSON提取器。 2. 配置JSON提取器参数 变量名称(Names of created…...
STM32中断
STM32 GPIO外部中断简图 中断向量表 定义一块固定的内存,以4字节对齐,存放各个中断服务函数程序的首地址 中断向量表定义在启动文件,当发生中断,CPU会自动执行对应的中断服务函数 中断向量表以及中断函数 NVIC嵌套向量中断控制…...
navicat 如何导出数据库表 的这些信息 字段名 类型 描述
navicat 如何导出数据库表 的这些信息 字段名 类型 描述 数据库名字 springbootmt74k 表名字 address SELECT COLUMN_NAME AS 字段名,COLUMN_TYPE AS 类型,COLUMN_COMMENT AS 描述 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA springbootmt74k AND TABLE_NAME a…...
LangGraph(三)——添加记忆
目录 1. 创建MemorySaver检查指针2. 构建并编译Graph3. 与聊天机器人互动4. 问一个后续问题5. 检查State参考 1. 创建MemorySaver检查指针 创建MemorySaver检查指针: from langgraph.checkpoint.memory import MemorySavermemory MemorySaver()这是位于内存中的检…...
数仓-可累计,半累加,不可累加指标,是什么,举例说明及解决方案
目录 1. 可累计指标定义:举例:解决方案: 2. 半累加指标定义:举例:解决方案: 3. 不可累加指标定义:举例:解决方案: 4. 总结对比5. 实际场景中的注意事项 这是数据仓库设计…...
Java ClassLoader双亲委派机制
Java ClassLoader双亲委派机制 1 什么是双亲委派模型 “类加载体系”及ClassLoader双亲委派机制。java程序中的 .java文件编译完会生成 .class文件,而 .class文件就是通过被称为类加载器的ClassLoader加载的,而ClassLoder在加载过程中会使用“双亲委派…...
upload-labs靶场通关详解:第四关
一、分析源代码 可以看出这一关仍然是黑名单验证,但是它禁止了更多的后缀。像php3,php4这类后缀也被加入了黑名单,第三关的方法在这里显然就失效了。那么我们想一想,既然配置文件中存在将php3当作php来执行的功能,那么…...
Webug4.0通关笔记25- 第30关SSRF
目录 一、SSRF简介 1.SSRF原理 2.渗透方法 二、第30关SSRF渗透实战 1.打开靶场 2.渗透实战 (1)Windows靶场修复 (2)Docker靶场修复 (3)获取敏感文件信息 (4)内网端口与服务…...
【 Redis | 实战篇 缓存 】
目录 前言: 1.认识缓存 2.添加Redis缓存 2.1.根据id查询商铺缓存 2.2.优化根据id查询商铺缓存 3.缓存更新策略 3.1.三种策略 3.2.策略选择 3.3.主动更新的方案 3.4. Cache Aside的模式选择 3.5.最佳实践方案 4.缓存三大问题 4.1.缓存穿透 4.1.1.介绍 …...
数字果园管理系统的设计与实现(Tensorflow的害虫识别结合高德API的害虫定位与Websocket的在线聊天室)
文章目录 技术栈主要功能害虫识别与定位害虫识别的实现训练与测试评估代码模型转化为TFLite预测脚本PredictController预测控制器害虫识别过程展示 害虫定位实现害虫定位代码害虫定位过程展示 专家咨询功能在线咨询聊天室主要前端代码如下主要后端代码如下 技术栈 Spring Boot…...
信息检索(包含源码)
实验目的 掌握逻辑回归模型在二分类问题中的应用方法熟悉机器学习模型评估指标PR曲线(精确率-召回率曲线)和ROC曲线(受试者工作特征曲线)的绘制与分析学习使用Python的scikit-learn库进行数据预处理、模型训练与评估理解特征选择…...
【金仓数据库征文】金仓数据库KingbaseES: 技术优势与实践指南(包含安装)
目录 前言 引言 一 : 关于KingbaseES,他有那些优势呢? 核心特性 典型应用场景 政务信息化 金融核心系统: 能源通信行业: 企业级信息系统: 二: 下载安装KingbaseES 三:目录一览表: 四:常用SQL语句 创建表: 修改表结构…...
Java数据结构——二叉树
二叉树 树的概念二叉树满二叉树和完全二叉树二叉树的性质二叉树的遍历 题目练习前序遍历中序遍历后序遍历 前言 已经知道了数据结构中的线性结构,那有没有非线性结构呢? 当然有就像我们文件夹,一个文件夹中有有另一个文件夹,这就是…...
用go从零构建写一个RPC(仿gRPC,tRPC)--- 版本2
在版本1中,虽然系统能够满足基本需求,但随着连接数的增加和处理请求的复杂度上升,性能瓶颈逐渐显现。为了进一步提升系统的稳定性、并发处理能力以及资源的高效利用,版本2引入了三个重要功能:客户端连接池、服务器长连…...
drf 使用jwt
安装jwt pip install pyJwt 添加登录url path("jwt/login",views.JwtLoginView.as_view(),namejwt-login),path("jwt/order",views.JwtOrderView.as_view(),namejwt-order), 创建视图 from django.contrib.auth import authenticateimport jwt from jw…...
202536 | KafKa生产者分区写入策略+消费者分区分配策略
KafKa生产者分区写入策略 1. 轮询分区策略(Round-Robin Partitioning) 轮询分区策略 是 Kafka 默认的分配策略,当消息没有指定 key 时,Kafka 会采用轮询的方式将消息均匀地分配到各个分区。 工作原理: 每次生产者发…...
《自动驾驶封闭测试场地建设技术要求》 GB/T 43119-2023——解读
目录 一、标准框架与核心内容 二、重点技术要求 三、实施要点与建议 四、实施时间与参考依据 原文链接:国家标准|GB/T 43119-2023 (发布:2023-09-07;实施:2024-01-01) 一、标准框架与核心内容 适用范围…...
【C++ Qt】容器类(GroupBox、TabWidget)内附思维导图 通俗易懂
每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” ✍️绪论: 本章主要介绍了 Qt 中 QGroupBox 与 QTabWidget 控件。QGroupBox 是带标题的分组框,能容纳其他控件,有标题、对齐方式、是否…...
【SpringBoot】从环境准备到创建SpringBoot项目的全面解析.
本篇博客给大家带来的是SpringBoot的知识点, 包括Idea的干净卸载… 🐎文章专栏: JavaEE初阶 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅🚀 要…...
基于ESP32控制的机器人摄像头车
DIY Wi-Fi 控制的机器人摄像头车:从零开始的智能探索之旅 在当今科技飞速发展的时代,机器人技术已经逐渐走进了我们的生活。今天,我将带你一起探索如何制作一个 Wi-Fi 控制的机器人摄像头车,它不仅可以远程操控,还能通…...
Excel图表 vs 专业可视化工具:差距有多大?内容摘要
你是不是还在用 Excel 做图表,觉得它已经够用了?但你知道吗,Excel 和专业的可视化工具之间其实有着巨大的差距!Excel 是办公必备,但它的图表功能真的能满足复杂的数据展示需求吗?而那些听起来高大上的专业可…...
Nacos源码—7.Nacos升级gRPC分析三
大纲 5.服务变动时如何通知订阅的客户端 6.微服务实例信息如何同步集群节点 5.服务变动时如何通知订阅的客户端 (1)服务注册和服务订阅时发布的客户端注册和订阅事件的处理 (2)延迟任务的执行引擎源码 (3)处理客户端注册和订阅事件时发布的服务变动和服务订阅事件的处理 (…...
量化学习DAY2-开始批量提交alpha!
量化学习第二天笔记 一、World Quant平台的Alpha概念 在World Quant平台中,alpha本质上是一个数学公式,它是**operator(操作)与Data(数据)**的组合。 (一)Data相关 Data…...
【Qwen3_ 4b lora xinli 】 task完成实践记录
task 我需要 基于llamafactory框架选取基本上相同的数据集用lora微调Qwen3_ 4b两次并保存lora参数然后分别合并这两个lora参数到基座模型。再换个数据集上接着进行微调。并且保存新的lora参数,然后我们匹配这里面的特征值和特征向量,如果这两个新的lora…...
文旅田园康养小镇规划设计方案PPT(85页)
1. 项目背景与定位 背景:位于长三角经济圈,依托安吉丰富的自然与文化资源,旨在打造集康养、度假、文化体验于一体的综合小镇。 定位:成为浙北地区知名的康养旅游目的地,融合“一溪两岸”规划理念,实现全面…...
[Windows] 能同时打开多个图片的图像游览器JWSEE v2.0
[Windows] 能同时打开多个图片的图像游览器JWSEE 链接:https://pan.xunlei.com/s/VOPpO86Hu3dalYLaZ1ivcTGIA1?pwdhckf# 十多年前收藏的能同时打开多个图片的图像游览器JWSEE v2.0,官网已没有下载资源。 JWSEE v2.0是乌鲁木齐金维图文信息科技有限公司…...
低成本自动化改造技术锚点深度解析
执行摘要 本文旨在深入剖析四项关键的低成本自动化技术,这些技术为工业转型提供了显著的运营和经济效益。文章将提供实用且深入的指导,涵盖老旧设备联网、AGV车队优化、空压机系统智能能耗管控以及此类项目投资回报率(ROI)的严谨…...
23盘古石决赛
一,流量分析 1. 计算流量包文件的SHA256值是?[答案:字母小写][★☆☆☆☆] 答案:2d689add281b477c82b18af8ab857ef5be6badf253db1c1923528dd73b3d61a9 解压出来流量包计算 2. 流量包长度在“640 - 1279”之间的的数据包总共有多少…...
C语言—指针3
1. 数组名的理解 观察以下代码 可以观察到pa指向的地址与数组首元素地址相同,那么可以说明数组就是首元素地址吗? 这种说法是不严谨的,观察以下代码: 程序输出的结果为16,此时的arr表示的是整个数组的大小。 观察以…...
操作系统 第2章节 进程,线程和作业
一:多道程序设计 1-多道程设计的目的 for:提高吞吐量(作业道数/处理时间),我们可以从提高资源的利用率出发 2-单道程序设计缺点: 设备的利用率低,内存的利用率低,处理机的利用率低 比如CPU去访问内存,CPU空转.内存等待CPU访问也是没有任何操作的.要是有多个东西要去访问不冲…...
数字化转型-4A架构之数据架构
系列文章 数字化转型-4A架构(业务架构、应用架构、数据架构、技术架构) 数字化转型-4A架构之业务架构 数字化转型-4A架构之应用架构 数据架构 Data Architecture(DA) 1. 定义 数据架构,是组织管理数据资产的科学之…...
Java中的反射
目录 什么是反射 反射的核心作用 反射的核心类 反射的基本使用 获取Class对象 创建对象 操作字段(Field) 调用方法(Method) 反射的应用场景 反射的优缺点 优点 缺点 示例:完整反射操作 总结 什么是反射 …...
LINUX CFS算法解析
文章目录 1. Linux调度器的发展历程2. CFS设计思想3. CFS核心数据结构3.1 调度实体(sched_entity)3.2 CFS运行队列(cfs_rq)3.3 任务结构体中的调度相关字段 4. 优先级与权重4.1 优先级范围4.2 权重映射表 (prio_to_weight[])优先级计算4.3.1. static_prio (静态优先级)4.3.2. n…...
内网渗透——红日靶场三
目录 一、前期准备 二、外网探测 1.使用nmap进行扫描 2.网站信息收集 3.漏洞复现(CVE-2021-23132) 4.disable_function绕过 5.反弹shell(也,并不是) 6.SSH登录 7.权限提升(脏牛漏洞) 8.信息收集 9.上线msf 三…...
The 2024 ICPC Kunming Invitational Contest G. Be Positive
https://codeforces.com/gym/105386/problem/G 题目: 结论: 从0开始每四个相邻数的异或值为0 代码: #include<bits/stdc.h> using namespace std; #define int long long void solve() {int n;cin >> n;if(n1||n%40){cout &…...
CommunityToolkit.Mvvm详解
属性可视化 给一个属性添加ObservableProperty就可以可视化了 [ObservableProperty] private string currentNameInfo;[ObservableProperty] private string currentClassInfo;[ObservableProperty] private string currentPhoneInfo;xaml中只需要绑定大写的属性就可以了 &l…...
密码学--AES
一、实验目的 1、完成AES算法中1轮加密和解密操作 2、掌握AES的4个基本处理步骤 3、理解对称加密算法的“对称”思想 二、实验内容 1、题目内容描述 (1)利用C语言实现字节代换和逆向字节代换,字节查S盒代换 (2)利…...
操作系统的初步了解
目录 引言:什么是操作系统? 一、设计操作系统的目的 二、操作系统是做什么的: 操作系统主要有四大核心任务: 1. 管理硬件 2. 运行软件 3. 存储数据 4. 提供用户界面 如何理解操作系统的管理呢? 1. 什么是操作…...
边缘计算:技术概念与应用详解
引言 随着物联网(IoT)、5G 和人工智能(AI)的快速发展,传统的云计算架构在处理海量数据和实时计算需求时逐渐显现出瓶颈。边缘计算(Edge Computing)作为一种新兴的计算范式,通过将计…...
C++进阶--红黑树的实现
文章目录 红黑树的实现红黑树的概念红黑树的规则红黑树的效率 红黑树的实现红黑树的结构红黑树的插入变色单旋(变色)双旋(变色) 红黑树的查找红黑树的验证 总结:结语 很高兴和大家见面,给生活加点impetus&a…...
[C++类和对象]类和对象的引入
面向过程和面向对象 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用来逐步解决问题 C是基于面向对象的,关注的是对象,将一件事情分成不同的对象,靠对象之间完成交互 类的引入 C语言结构体中只能定义变量,在C中,结构体不仅仅可以定义变量,而且可以定义函…...
YOLOv12云端GPU谷歌免费版训练模型
1.效果 2.打开 https://colab.research.google.com/?utm_sourcescs-index 3.上传代码 4.解压 !unzip /content/yolov12-main.zip -d /content/yolov12-main 5.进入yolov12-main目录 %cd /content/yolov12-main/yolov12-main 6.安装依赖库 !pip install -r requirements.…...
课程审核流程揭秘:确保内容合规与用户体验
业务流程 为什么课程审核通过才可以发布呢? 这样做为了防止课程信息有违规情况,课程信息不完善对网站用户体验也不好,课程审核不仅起到监督作用,也是 帮助教学机构规范使用平台的手段。 如果流程复杂用工作流 说明如下ÿ…...
【LangChain高级系列】LangGraph第一课
前言 我们今天直接通过一个langgraph的基础案例,来深入探索langgraph的核心概念和工作原理。 基本认识 LangGraph是一个用于构建具有LLMs的有状态、多角色应用程序的库,用于创建代理和多代理工作流。与其他LLM框架相比,它提供了以下核心优…...
ATH12K 驱动框架
ATH12K 驱动框架 ath12k驱动框架及模块交互逻辑详解1. 总体架构2. 关键数据结构2.1 核心数据结构2.2 虚拟接口数据结构3. 硬件抽象层(HAL)4. 无线管理接口(WMI)5. 主机目标通信(HTC)6. 数据路径(DP)6.1 发送路径(TX)6.2 接收路径(RX)7. 多链路操作(MLO)8. 初始化和工作流程8.1 …...
CMA认证对象?CMA评审依据,CMA认证好处
CMA认证对象 CMA(中国计量认证,China Metrology Accreditation)的认证对象主要是第三方检测机构和实验室,包括: 独立检测机构:如环境监测站、产品质量检验所、食品药品检测机构等。 企业内部实验室&#…...
依赖关系-根据依赖关系求候选码
关系模式R(U, F), U{},F是R的函数依赖集,可以将属性分为4类: L: 仅出现在依赖集F左侧的属性 R: 仅出现在依赖集F右侧的属性 LR: 在依赖集F左右侧都出现的属性 NLR: 在依赖集F左右侧都未出现的属性 结论1: 若X是L类…...
解决应用程序在JAR包中运行时无法读取类路径下文件的问题
问题情景 java应用程序在IDE运行正常,打成jar包后执行却发生异常: java.io.FileNotFoundException: class path resource [cert/sync_signer_pri_test.key] cannot be resolved to absolute file path because it does not reside in the file system:…...
第十六届蓝桥杯B组第二题
当时在考场的时候这一道题目 无论我是使用JAVA的大数(BIGTHGER)还是赛后 使用PY 都是没有运行出来 今天也是突发奇想在B站上面搜一搜 看了才知道这也是需要一定的数学思维 通过转换 设X来把运算式精简化 避免运行超时 下面则是代码 public class lanba…...