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

Android开机动画

Android开机动画

  • 1、BootLoader开机图片
  • 2、Kernel开机图片
  • 3、系统启动时(BootAnimation)动画
    • 3.1 bootanimation.zip位置
    • 3.2 bootanimation启动
    • 3.3 SurfaceFlinger启动bootanimation
    • 3.4 播放开机动画playAnimation
    • 3.6 开机动画退出检测
    • 3.7 简易时序图
  • 4、bootanimation.zip文件

android12-release
推荐 Android 12 开机动画代码与流程详解


在这里插入图片描述

1、BootLoader开机图片

一般使用rle格式图片;例如放在splash分区

adb reboot bootloader
fastboot flash splash splash.img
fastboot reboot

2、Kernel开机图片

记录 kernel/drivers/video/msm/msm_fb.c 也是读出根目录下的xx.rle,并显示为开机画面

3、系统启动时(BootAnimation)动画

使用BootAnimation程序显示开机画面,如需修改开机画面,不用修改代码,只需按格式要求做bootanimation.zip包,放在系统的/system/media目录中,或/oem/media/product/media等目录。

代码路径:frameworks/base/cmds/bootanimation

3.1 bootanimation.zip位置

frameworks/base/cmds/bootanimation/BootAnimation.cpp,例如bootanimation.zip
在这里插入图片描述

3.2 bootanimation启动

frameworks/base/cmds/bootanimation/Android.bp
frameworks/base/cmds/bootanimation/bootanim.rc
frameworks/base/cmds/bootanimation/bootanimation_main.cpp
frameworks/base/cmds/bootanimation/BootAnimation.cpp
frameworks/base/cmds/bootanimation/BootAnimationUtil.cpp

SurfaceFlinger进程名:bootanim
bin文件:/system/bin/bootanimation
对应启动入口:/frameworks/base/cmds/bootanimation/bootanimation_main.cpp

bootAnimationDisabled()检测系统属性(debug.sf.nobootanimation、ro.boot.quiescent、ro.bootanim.quiescent.enabled),noBootAnimation 是否启动开机动画。注意init进程在启动bootanimation服务是disable的,不会主动将应用程序bootanimation启动起来。启动bootanimation是从surfaceFlinger这边来启动的

frameworks/base/cmds/bootanimation/bootanimation_main.cpp

int main()
{setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);bool noBootAnimation = bootAnimationDisabled();ALOGI_IF(noBootAnimation,  "boot animation disabled");if (!noBootAnimation) {sp<ProcessState> proc(ProcessState::self());ProcessState::self()->startThreadPool();// create the boot animation object (may take up to 200ms for 2MB zip)sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());waitForSurfaceFlinger();boot->run("BootAnimation", PRIORITY_DISPLAY);ALOGV("Boot animation set up. Joining pool.");IPCThreadState::self()->joinThreadPool();}return 0;
}

frameworks/base/cmds/bootanimation/BootAnimationUtil.cpp

bool bootAnimationDisabled() {char value[PROPERTY_VALUE_MAX];property_get("debug.sf.nobootanimation", value, "0");if (atoi(value) > 0) {return true;}property_get("ro.boot.quiescent", value, "0");if (atoi(value) > 0) {// Only show the bootanimation for quiescent boots if this system property is set to enabledif (!property_get_bool("ro.bootanim.quiescent.enabled", false)) {return true;}}return false;
}

3.3 SurfaceFlinger启动bootanimation

SurfaceFlinger启动-Android12 初始化时候 mStartPropertySetThread->Start() 在线程中设置property_set("ctl.start", "bootanim")启动开机动画

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp

#include <cutils/properties.h>
#include "StartPropertySetThread.h"namespace android {StartPropertySetThread::StartPropertySetThread(bool timestampPropertyValue):Thread(false), mTimestampPropertyValue(timestampPropertyValue) {}status_t StartPropertySetThread::Start() {return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
}bool StartPropertySetThread::threadLoop() {// Set property service.sf.present_timestamp, consumer need check its readinessproperty_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");// Clear BootAnimation exit flagproperty_set("service.bootanim.exit", "0");property_set("service.bootanim.progress", "0");// Start BootAnimation if not startedproperty_set("ctl.start", "bootanim");// Exit immediatelyreturn false;
}} // namespace android

3.4 播放开机动画playAnimation

  • result = android()android原生动画;result = movie()自动动画
  • playAnimation(*mAnimation)播放动画;releaseAnimation(mAnimation)释放动画资源
  • 播放动画过程:initTexture(frame.map, &w, &h)drawClock(animation.clockFont, part.clockPosX, part.clockPosY)drawProgress(lastDisplayedProgress, animation.progressFont, posX, posY)checkExit()
  • checkExit()检测属性"service.bootanim.exit"退出动画
bool BootAnimation::threadLoop() {bool result;// We have no bootanimation file, so we use the stock android logo// animation.if (mZipFileName.isEmpty()) {result = android();} else {result = movie();}mCallbacks->shutdown();eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);eglDestroyContext(mDisplay, mContext);eglDestroySurface(mDisplay, mSurface);mFlingerSurface.clear();mFlingerSurfaceControl.clear();eglTerminate(mDisplay);eglReleaseThread();IPCThreadState::self()->stopProcess();return result;
}
bool BootAnimation::movie() {if (mAnimation == nullptr) {mAnimation = loadAnimation(mZipFileName);}if (mAnimation == nullptr)return false;// mCallbacks->init() may get called recursively,// this loop is needed to get the same resultsfor (const Animation::Part& part : mAnimation->parts) {if (part.animation != nullptr) {mCallbacks->init(part.animation->parts);}}mCallbacks->init(mAnimation->parts);bool anyPartHasClock = false;for (size_t i=0; i < mAnimation->parts.size(); i++) {if(validClock(mAnimation->parts[i])) {anyPartHasClock = true;break;}}if (!anyPartHasClock) {mClockEnabled = false;}// Check if npot textures are supportedmUseNpotTextures = false;String8 gl_extensions;const char* exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));if (!exts) {glGetError();} else {gl_extensions.setTo(exts);if ((gl_extensions.find("GL_ARB_texture_non_power_of_two") != -1) ||(gl_extensions.find("GL_OES_texture_npot") != -1)) {mUseNpotTextures = true;}}// Blend required to draw time on top of animation frames.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glShadeModel(GL_FLAT);glDisable(GL_DITHER);glDisable(GL_SCISSOR_TEST);glDisable(GL_BLEND);glBindTexture(GL_TEXTURE_2D, 0);glEnable(GL_TEXTURE_2D);glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);bool clockFontInitialized = false;if (mClockEnabled) {clockFontInitialized =(initFont(&mAnimation->clockFont, CLOCK_FONT_ASSET) == NO_ERROR);mClockEnabled = clockFontInitialized;}initFont(&mAnimation->progressFont, PROGRESS_FONT_ASSET);if (mClockEnabled && !updateIsTimeAccurate()) {mTimeCheckThread = new TimeCheckThread(this);mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL);}playAnimation(*mAnimation);if (mTimeCheckThread != nullptr) {mTimeCheckThread->requestExit();mTimeCheckThread = nullptr;}if (clockFontInitialized) {glDeleteTextures(1, &mAnimation->clockFont.texture.name);}releaseAnimation(mAnimation);mAnimation = nullptr;return false;
}
bool BootAnimation::playAnimation(const Animation& animation) {const size_t pcount = animation.parts.size();nsecs_t frameDuration = s2ns(1) / animation.fps;SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",elapsedRealtime());int fadedFramesCount = 0;int lastDisplayedProgress = 0;for (size_t i=0 ; i<pcount ; i++) {const Animation::Part& part(animation.parts[i]);const size_t fcount = part.frames.size();glBindTexture(GL_TEXTURE_2D, 0);// Handle animation packageif (part.animation != nullptr) {playAnimation(*part.animation);if (exitPending())break;continue; //to next part}// process the part not only while the count allows but also if already fadingfor (int r=0 ; !part.count || r<part.count || fadedFramesCount > 0 ; r++) {if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break;mCallbacks->playPart(i, part, r);glClearColor(part.backgroundColor[0],part.backgroundColor[1],part.backgroundColor[2],1.0f);// For the last animation, if we have progress indicator from// the system, display it.int currentProgress = android::base::GetIntProperty(PROGRESS_PROP_NAME, 0);bool displayProgress = animation.progressEnabled &&(i == (pcount -1)) && currentProgress != 0;for (size_t j=0 ; j<fcount ; j++) {if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break;processDisplayEvents();const int animationX = (mWidth - animation.width) / 2;const int animationY = (mHeight - animation.height) / 2;const Animation::Frame& frame(part.frames[j]);nsecs_t lastFrame = systemTime();if (r > 0) {glBindTexture(GL_TEXTURE_2D, frame.tid);} else {if (part.count != 1) {glGenTextures(1, &frame.tid);glBindTexture(GL_TEXTURE_2D, frame.tid);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);}int w, h;initTexture(frame.map, &w, &h);}const int xc = animationX + frame.trimX;const int yc = animationY + frame.trimY;Region clearReg(Rect(mWidth, mHeight));clearReg.subtractSelf(Rect(xc, yc, xc+frame.trimWidth, yc+frame.trimHeight));if (!clearReg.isEmpty()) {Region::const_iterator head(clearReg.begin());Region::const_iterator tail(clearReg.end());glEnable(GL_SCISSOR_TEST);while (head != tail) {const Rect& r2(*head++);glScissor(r2.left, mHeight - r2.bottom, r2.width(), r2.height());glClear(GL_COLOR_BUFFER_BIT);}glDisable(GL_SCISSOR_TEST);}// specify the y center as ceiling((mHeight - frame.trimHeight) / 2)// which is equivalent to mHeight - (yc + frame.trimHeight)const int frameDrawY = mHeight - (yc + frame.trimHeight);glDrawTexiOES(xc, frameDrawY, 0, frame.trimWidth, frame.trimHeight);// if the part hasn't been stopped yet then continue fading if necessaryif (exitPending() && part.hasFadingPhase()) {fadeFrame(xc, frameDrawY, frame.trimWidth, frame.trimHeight, part,++fadedFramesCount);if (fadedFramesCount >= part.framesToFadeCount) {fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading}}if (mClockEnabled && mTimeIsAccurate && validClock(part)) {drawClock(animation.clockFont, part.clockPosX, part.clockPosY);}if (displayProgress) {int newProgress = android::base::GetIntProperty(PROGRESS_PROP_NAME, 0);// In case the new progress jumped suddenly, still show an// increment of 1.if (lastDisplayedProgress != 100) {// Artificially sleep 1/10th a second to slow down the animation.usleep(100000);if (lastDisplayedProgress < newProgress) {lastDisplayedProgress++;}}// Put the progress percentage right below the animation.int posY = animation.height / 3;int posX = TEXT_CENTER_VALUE;drawProgress(lastDisplayedProgress, animation.progressFont, posX, posY);}handleViewport(frameDuration);eglSwapBuffers(mDisplay, mSurface);nsecs_t now = systemTime();nsecs_t delay = frameDuration - (now - lastFrame);//SLOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay));lastFrame = now;if (delay > 0) {struct timespec spec;spec.tv_sec  = (now + delay) / 1000000000;spec.tv_nsec = (now + delay) % 1000000000;int err;do {err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, nullptr);} while (err<0 && errno == EINTR);}checkExit();}usleep(part.pause * ns2us(frameDuration));if (exitPending() && !part.count && mCurrentInset >= mTargetInset &&!part.hasFadingPhase()) {if (lastDisplayedProgress != 0 && lastDisplayedProgress != 100) {android::base::SetProperty(PROGRESS_PROP_NAME, "100");continue;}break; // exit the infinite non-fading part when it has been played at least once}}}// Free textures created for looping parts now that the animation is done.for (const Animation::Part& part : animation.parts) {if (part.count != 1) {const size_t fcount = part.frames.size();for (size_t j = 0; j < fcount; j++) {const Animation::Frame& frame(part.frames[j]);glDeleteTextures(1, &frame.tid);}}}return true;
}

3.6 开机动画退出检测

  • checkExit()检测属性"service.bootanim.exit"退出动画;在playAnimation方法和android方法中都有一个checkExit方法来负责检查是否退出动画
  • WMS中performEnableScreen()设置SystemProperties.set("service.bootanim.exit", "1")
void BootAnimation::checkExit() {// Allow surface flinger to gracefully request shutdownchar value[PROPERTY_VALUE_MAX];property_get(EXIT_PROP_NAME, value, "0");int exitnow = atoi(value);if (exitnow) {requestExit();}
}

在这里插入图片描述

private void performEnableScreen() {synchronized (mGlobalLock) {ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: mDisplayEnabled=%b"+ " mForceDisplayEnabled=%b" + " mShowingBootMessages=%b"+ " mSystemBooted=%b mOnlyCore=%b. %s", mDisplayEnabled,mForceDisplayEnabled, mShowingBootMessages, mSystemBooted, mOnlyCore,new RuntimeException("here").fillInStackTrace());if (mDisplayEnabled) {return;}if (!mSystemBooted && !mShowingBootMessages) {return;}if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {return;}// Don't enable the screen until all existing windows have been drawn.if (!mForceDisplayEnabled) {if (mBootWaitForWindowsStartTime < 0) {// First time we will start waiting for all windows to be drawn.mBootWaitForWindowsStartTime = SystemClock.elapsedRealtime();}for (int i = mRoot.getChildCount() - 1; i >= 0; i--) {if (mRoot.getChildAt(i).shouldWaitForSystemDecorWindowsOnBoot()) {return;}}long waitTime = SystemClock.elapsedRealtime() - mBootWaitForWindowsStartTime;mBootWaitForWindowsStartTime = -1;if (waitTime > 10) {ProtoLog.i(WM_DEBUG_BOOT,"performEnableScreen: Waited %dms for all windows to be drawn",waitTime);}}if (!mBootAnimationStopped) {Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);// stop boot animation// formerly we would just kill the process, but we now ask it to exit so it// can choose where to stop the animation.SystemProperties.set("service.bootanim.exit", "1");mBootAnimationStopped = true;}if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {ProtoLog.i(WM_DEBUG_BOOT, "performEnableScreen: Waiting for anim complete");return;}try {IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");if (surfaceFlinger != null) {ProtoLog.i(WM_ERROR, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");Parcel data = Parcel.obtain();data.writeInterfaceToken("android.ui.ISurfaceComposer");surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHEDdata, null, 0);data.recycle();}} catch (RemoteException ex) {ProtoLog.e(WM_ERROR, "Boot completed: SurfaceFlinger is dead!");}EventLogTags.writeWmBootAnimationDone(SystemClock.uptimeMillis());Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);mDisplayEnabled = true;ProtoLog.i(WM_DEBUG_SCREEN_ON, "******************** ENABLING SCREEN!");// Enable input dispatch.mInputManagerCallback.setEventDispatchingLw(mEventDispatchingEnabled);}try {mActivityManager.bootAnimationComplete();} catch (RemoteException e) {}mPolicy.enableScreenAfterBoot();// Make sure the last requested orientation has been applied.updateRotationUnchecked(false, false);
}

3.7 简易时序图

在这里插入图片描述

4、bootanimation.zip文件

bootanimation.zip
在这里插入图片描述 在这里插入图片描述
bootanimation.zip\desc.txt:

1080 2400 5
p 0 5 part0

bootanimation.zip\part0:
在这里插入图片描述

相关文章:

Android开机动画

Android开机动画 1、BootLoader开机图片2、Kernel开机图片3、系统启动时&#xff08;BootAnimation&#xff09;动画3.1 bootanimation.zip位置3.2 bootanimation启动3.3 SurfaceFlinger启动bootanimation3.4 播放开机动画playAnimation3.6 开机动画退出检测3.7 简易时序图 4、…...

vue中使用wow.js

一、安装 npm install wowjs --save-dev 二、main中引入 animate.css会自动安装 因为wow.js在animate.css基础上 main.js中引入animate.css import "animate.css" 三、 页面使用 有两种引入使用方式&#xff1a;1. import {WOW} from wowjs mounted() { n…...

网站edge -- 油猴 -> IDM

一、百度网盘限速 未解决 软件&#xff1a;IDM 安装路径&#xff1a; 1.1如果&#xff1a;edge 出问题打不开其他网站&#xff0c; 解决方法&#xff1a; 以管理员的身份&#xff0c;右击载这个软件&#xff0c;就好了 1.2使用这个软件 应该是右击这个软件 以管理员的身…...

Android片段

如果你希望应用根据不同的环境有不同的外观和行为&#xff0c;这种情况下就需要片段&#xff0c;片段是可以由不同活动重用的模块化代码组件。 片段&#xff08;Fragment&#xff09;是活动&#xff08;Activity&#xff09;的一种模块化部分&#xff0c;表示活动中的行为或界面…...

iOS实时监控与报警器

在现代信息化社会中&#xff0c;即使我们不在电脑前面也能随时获取到最新的数据。而苹果公司提供的iOS推送通知功能为我们带来了一种全新的方式——通过手机接收实时监控和报警信息。 首先让我们了解一下iOS推送通知。它是一个强大且灵活可定制化程度高、适用于各类应用场景&a…...

Git小白入门——上手实操之创建仓库和代码提交

版本库 什么是版本库呢&#xff1f;版本库又名仓库&#xff0c;英文名repository&#xff0c;简单理解成一个目录&#xff0c;目录里的所有文件都可以被Git管理&#xff0c;每个文件的修改、删除&#xff0c;Git都能跟踪&#xff0c;以便任何时刻都可以追踪历史&#xff0c;或…...

JS数组迭代方法实操

数组迭代方法有 1. every() 2.some() 3.foreach() 4.map() 5.filter 逐一操作&#xff0c;并简要区分之。 1 every() every() 方法使用指定的函数测试数组中所有的项&#xff0c;在数组的所有项都满足该条件时&#xff0c;才返回true&#xff0c;否则返回false&#xff1b; …...

基于snat+dnat发布内网K8S及Jenkins+gitlab+Harbor模拟CI/CD的综合项目

目录 项目名称 项目架构图 项目环境 项目概述 项目准备 项目步骤 一、修改每台主机的ip地址&#xff0c;同时设置永久关闭防火墙和selinux&#xff0c;修改好主机名&#xff0c;在firewalld服务器上开启路由功能并配置snat策略。 1. 在firewalld服务器上配置ip地址、设…...

时序预测 | MATLAB实现PSO-LSSVM粒子群算法优化最小二乘支持向量机时间序列预测未来

时序预测 | MATLAB实现PSO-LSSVM粒子群算法优化最小二乘支持向量机时间序列预测未来 目录 时序预测 | MATLAB实现PSO-LSSVM粒子群算法优化最小二乘支持向量机时间序列预测未来预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.Matlab实现PSO-LSSVM时间序列预测未…...

java IO流(二) 字符流 缓冲流 原始流与缓冲流性能分析

字符流 前面学习的字节流虽然可以读取文件中的字节数据&#xff0c;但是如果文件中有中文&#xff0c;使用字节流来读取&#xff0c;就有可能读到半个汉字的情况&#xff0c;这样会导致乱码。虽然使用读取全部字节的方法不会出现乱码&#xff0c;但是如果文件过大又不太合适。…...

复现XSS漏洞及分析

XSS漏洞概述&#xff1a; 类型一&#xff1a;反射型 类型二&#xff1a;存储型 类型三&#xff1a;DOM型 复现20字符短域名绕过 一、安装BEEF 1、在Kali中运行apt install beef-xss 2、运行beef 3、在浏览器访问 二、安装galleryCMS *遇到一点小问题 提示"last…...

Vue组件之间传值

聊一聊vue里面组件之间的传值 首先总结一下vue里面传值的几种关系&#xff1a; 如上图所示, A与B、A与C、B与D、C与F组件之间是父子关系&#xff1b; B与C之间是兄弟关系&#xff1b;A与D、A与E之间是隔代关系&#xff1b; D与F是堂兄关系&#xff0c;针对以上关系 我们把组件…...

windows查看端口占用,通过端口找进程号(查找进程号),通过进程号定位应用名(查找应用)(netstat、tasklist)

文章目录 通过端口号查看进程号netstat通过进程号定位应用程序tasklist 通过端口号查看进程号netstat 在Windows系统中&#xff0c;可以使用 netstat 命令来查看端口的占用情况。以下是具体的步骤&#xff1a; 打开命令提示符&#xff08;CMD&#xff09;&#xff1a;按WinR组…...

Weblogic SSRF【漏洞复现】

文章目录 漏洞测试注入HTTP头&#xff0c;利用Redis反弹shell redis不能启动问题解决 Path : vulhub/weblogic/ssrf 编译及启动测试环境 docker compose up -dWeblogic中存在一个SSRF漏洞&#xff0c;利用该漏洞可以发送任意HTTP请求&#xff0c;进而攻击内网中redis、fastcgi…...

文件读取漏洞复现(Metinfo 6.0.0)

文章目录 安装环境启动环境漏洞复现代码审计 安装环境 安装phpstudy&#xff0c;下载MetInfo 6.0.0版本软件&#xff0c;复制到phpstudy目录下的www目录中。 打开phpstudy&#xff0c;访问浏览器127.0.0.1/MetInfo6.0.0/install/index.php&#xff0c;打开Meinfo 6.0.0主页&a…...

【工程实践】使用git clone 批量下载huggingface模型文件

前言 经常需要下载模型到服务器&#xff0c;使用git clone方法可以快速实现模型下载。 1.选定要下载的模型 以下载moka-ai/m3e-base为例&#xff0c;切换到Files and versions。 2.更改下载网页的url 如上图所示&#xff0c;当前要下载模型网页的url为&#xff1a; https://hu…...

2020 杭电多校第三场 H Triangle Collision(反射套路 + 绕点旋转 + 矢量

2020 杭电多校第三场 H. Triangle Collision(反射套路 绕点旋转 矢量分解) 大意&#xff1a;给出一个等边三角形 &#xff0c; 以底边中线建立坐标系 &#xff0c; 给出三角形中一点 &#xff0c; 和其初始速度 &#xff0c; 小球在等边三角形中做完全弹性碰撞 &#xff0c; …...

Servlet属性、监听者和会话

没有servlet能单独存在。在当前的现代Web应用中&#xff0c;许多组件都是在一起协作共同完成一个目标。怎么让这些组件共享信息&#xff1f;如何隐藏信息&#xff1f;怎样让信息做到线程安全&#xff1f; 1 属性和监听者 1.1 初始化 容器初始化一个servlet时&#xff0c;会为…...

Gin学习记录2——路由

路由 一. 常规路由二. 动态路由三. 带参数的路由3.1 GET3.2 POST3.3 绑定 四. 简单的路由组五. 文件分组 一. 常规路由 package mainimport ("net/http""github.com/gin-gonic/gin" )func index(ctx *gin.Context) {ctx.String(http.StatusOK, "Hell…...

《计算机算法设计与分析》第一章:算法概述

第一章 算法概述 1.1 算法复杂性分析 公共标准&#xff1a;渐进时间复杂度 &#xff08;1&#xff09;大O表示法&#xff1a; 例如&#xff1a; 大O表示法和前面的最坏时间复杂度的区别在于&#xff1a;大O表示法表示的更为简洁&#xff0c; 而最坏时间复杂度相对就比较繁琐&am…...

华为数通方向HCIP-DataCom H12-821题库(单选题:201-220)

第201题 BGP 协议用​​ beer default-route-advertise​​ 命令来给邻居发布缺省路由,那么以下关于本地 BGP 路由表变化的描述&#xff0c;正确的是哪一项? A、在本地 BGP 路由表中生成一条活跃的缺省路由并下发给路由表 B、在本地 BGP 路由表中生成一条不活跃的缺省路由&…...

使用ELK收集解析nginx日志和kibana可视化仪表盘

文章目录 ELK生产环境配置filebeat 配置logstash 配置 kibana仪表盘配置配置nginx转发ES和kibanaELK设置账号和密码 ELK生产环境配置 ELK收集nginx日志有多种方案&#xff0c;一般比较常见的做法是在生产环境服务器搭建filebeat 收集nginx的文件日志并写入到队列&#xff08;k…...

【Sentinel】ProcessorSlotChain处理器插槽链与Node

文章目录 1、Sentinel的基本概念2、ProcessorSlotChain3、Node 1、Sentinel的基本概念 Sentinel实现限流、隔离、降级、熔断等功能&#xff0c;本质要做的就是两件事情&#xff1a; 统计数据&#xff1a;统计某个资源的访问数据&#xff08;QPS、RT等信息&#xff09;规则判断…...

数据库管理系统(DBMS)的事务四大特性(ACID)以及事务的四种隔离级别

一、什么是ACID&#xff1f; ACID是原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;和持久性&#xff08;Durability&#xff09; 的缩写&#xff0c;是在可靠数据库管理系统&#xff08;DBMS&…...

leetcode 234. 回文链表

2023.9.5 本题先将链表的节点值移到数组中&#xff0c;再用双指针去判断该数组是否为回文的即可。 代码如下&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* …...

Scala集合继承体系图

Scala集合简介 1&#xff09; Scala 的集合有三大类&#xff1a;序列 Seq、集Set、映射 Map&#xff0c;所有的集合都扩展自 Iterable特质。 2&#xff09; 对于几乎所有的集合类&#xff0c;Scala 都同时提供了可变和不可变的版本&#xff0c;分别位于以下两个包 不可变集合…...

《Go 语言第一课》课程学习笔记(十五)

并发 Go 的并发方案&#xff1a;goroutine 并行&#xff08;parallelism&#xff09;&#xff0c;指的就是在同一时刻&#xff0c;有两个或两个以上的任务&#xff08;这里指进程&#xff09;的代码在处理器上执行。 并发不是并行&#xff0c;并发关乎结构&#xff0c;并行关…...

练习 Qt 实时显示鼠标坐标位置

Qt 入门实战教程&#xff08;目录&#xff09; 前驱课程 本文是文章 Qt鼠标点击事件处理&#xff1a;显示鼠标点击位置&#xff08;完整示例&#xff09; 的一个作业&#xff08;下文称之为“前驱课程”&#xff09;。 前驱课程中&#xff0c;我们完整的展示了如何在QtCreat…...

Leetcode130. 被围绕的区域

Every day a Leetcode 题目来源&#xff1a;130. 被围绕的区域 本题给定的矩阵中有三种元素&#xff1a; 字母 X&#xff1b;被字母 X 包围的字母 O&#xff1b;没有被字母 X 包围的字母 O。 本题要求将所有被字母 X 包围的字母 O都变为字母 X &#xff0c;但很难判断哪些 …...

6.xpath的基本使用

xpath是python做数据解析的库 目录 1 安装 2 解析本地的html文件 2.1 只有一个标签的情况 2.2 有多个标签的情况 3 解析网上的页面 4 xpath表达式 4.1 绝对路径 4.2 两个斜杠表示中间隔了0级或多级 4.3 通过属性查找 4.4 通过索引查找 4.5 获取文本内容…...