健身餐的网站怎么做/营销型网站建设步骤
首语
在Android设备开机启动时,会展示Android开机动画,用于增加用户体验和展示设备品牌等信息。它也是Android系统启动的一部分。开机动画是由bootanimation负责的,因此首先先了解下bootanimation是如何启动的。
bootanimation 启动脚本分析
init进程中第二阶段(SecondStageMain)的主要工作有初始化属性服务,加载启动脚本,解析init.rc文件等。
源码路径:system/core/init/init.cpp
int SecondStageMain(int argc, char** argv) {...LoadBootScripts(am, sm);...
}
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {Parser parser = CreateParser(action_manager, service_list);std::string bootscript = GetProperty("ro.boot.init_rc", "");if (bootscript.empty()) {parser.ParseConfig("/system/etc/init/hw/init.rc");if (!parser.ParseConfig("/system/etc/init")) {late_import_paths.emplace_back("/system/etc/init");}// late_import is available only in Q and earlier release. As we don't// have system_ext in those versions, skip late_import for system_ext.parser.ParseConfig("/system_ext/etc/init");if (!parser.ParseConfig("/vendor/etc/init")) {late_import_paths.emplace_back("/vendor/etc/init");}if (!parser.ParseConfig("/odm/etc/init")) {late_import_paths.emplace_back("/odm/etc/init");}if (!parser.ParseConfig("/product/etc/init")) {late_import_paths.emplace_back("/product/etc/init");}} else {parser.ParseConfig(bootscript);}
}
在init.rc文件中,可以看到通过class_start来启动 classname 为 core 的 Service。在bootanimation.rc文件中,可以清楚看到Service name为bootanim,执行程序路径为:/system/bin/bootanimation,类名:core。disabled表示系统启动时,不会自动启动bootanimation。那是谁启动bootanimation呢?
SurfaceFlinger它负责管理图形内容的渲染,并将多个图层(包括应用程序窗口、系统UI元素和硬件覆盖层)合成到设备的屏幕上。所以首先需要启动SurfaceFlinger,开机动画的渲染和合成是它完成的,继续分析SurfaceFlinger启动流程。
源码路径:system/core/rootdir/init.rc
...# Start standard binderized HAL daemonsclass_start halclass_start core
...
源码路径:frameworks/base/cmds/bootanimation/bootanim.rc
service bootanim /system/bin/bootanimationclass core animationuser graphicsgroup graphics audiodisabledoneshotioprio rt 0task_profiles MaxPerformance
SurfaceFlinger启动流程
而surfaceflinger.rc文件中,可以清楚看到Service name为surfaceflinger,执行程序路径为:/system/bin/surfaceflinger,类名:core。
因此,可以知道SurfaceFlinger是在init进程启动第二阶段进行启动的。
源码路径:frameworks/native/services/surfaceflinger/surfaceflinger.rc
service surfaceflinger /system/bin/surfaceflingerclass core animationuser systemgroup graphics drmrpc readproccapabilities SYS_NICEonrestart restart --only-if-running zygotetask_profiles HighPerformancesocket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
看下SurfaceFlinger的main函数,创建了SurfaceFlinger并且初始化,调用StartPropertySetThread的Start函数。
源码路径:frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
int main(int, char**) {...// instantiate surfaceflingersp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();...// initialize before clients can connectflinger->init();...
}
源码路径:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() {...mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable);if (mStartPropertySetThread->Start() != NO_ERROR) {ALOGE("Run StartPropertySetThread failed!");}...
}
可以看到将系统属性service.bootanim.exit/service.bootanim.progress设置为0,并将ctl.start设置为bootanim,当系统属性发生改变时,init进程就会接收到一个系统属性变化通知,这个通知最终是由在init进程中的函数handle_property_set_fd来处理的。设置ctl.start表示启动一个服务,这样bootanimation就被启动了。
源码路径:frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp
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;
}
bootanimation启动流程
分析bootanimation的main函数,首先判断是否禁用了启动动画,没有则创建一个binder线程池,再创建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) {//创建binder线程池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 enabled//禁用启动动画if (!property_get_bool("ro.bootanim.quiescent.enabled", false)) {return true;}}return false;
}void waitForSurfaceFlinger() {// TODO: replace this with better waiting logic in future, b/35253872int64_t waitStartTime = elapsedRealtime();sp<IServiceManager> sm = defaultServiceManager();const String16 name("SurfaceFlinger");const int SERVICE_WAIT_SLEEP_MS = 100;const int LOG_PER_RETRIES = 10;int retry = 0;while (sm->checkService(name) == nullptr) {retry++;if ((retry % LOG_PER_RETRIES) == 0) {ALOGW("Waiting for SurfaceFlinger, waited for %" PRId64 " ms",elapsedRealtime() - waitStartTime);}usleep(SERVICE_WAIT_SLEEP_MS * 1000);};int64_t totalWaited = elapsedRealtime() - waitStartTime;if (totalWaited > SERVICE_WAIT_SLEEP_MS) {ALOGI("Waiting for SurfaceFlinger took %" PRId64 " ms", totalWaited);}
}
BootAnimation类有几个重要函数
- onFirstRef(),属于父类RefBase,它用于实现引用计数的对象管理,新增引用计数时调用。
- binderDied() ,Binder结束时,就会回调binderDied()方法。
- readyToRun() ,Thread执行前的初始化工作。
- threadLoop() ,线程根据逻辑是否循环执行。
- android(),显示系统默认的开机画面。
- movie(),显示用户自定义的开机动画。
- loadAnimation(),加载动画。
- playAnimation(),播放动画。
- checkExit(),检查是否退出动画。
源码路径:frameworks/base/cmds/bootanimation/BootAnimation.h
private:virtual bool threadLoop();virtual status_t readyToRun();virtual void onFirstRef();virtual void binderDied(const wp<IBinder>& who);...//系统默认的开机画面bool android();//用户自定义的开机动画bool movie();...//加载动画Animation* loadAnimation(const String8&);//播放动画bool playAnimation(const Animation&);void releaseAnimation(Animation*) const;bool parseAnimationDesc(Animation&);bool preloadZip(Animation &animation);void findBootAnimationFile();bool findBootAnimationFileInternal(const std::vector<std::string>& files);bool preloadAnimation();EGLConfig getEglConfig(const EGLDisplay&);ui::Size limitSurfaceSize(int width, int height) const;void resizeSurface(int newWidth, int newHeight);void projectSceneToWindow();bool shouldStopPlayingPart(const Animation::Part& part, int fadedFramesCount,int lastDisplayedProgress);//检查是否退出动画void checkExit();
BootAnimation构造函数中,创建了SurfaceComposerClient,mSession用来和SurfaceFlinger执行Binder进程间通信,执行linkToComposerDeath方法用于获取SurfaceFlinger死亡通知,preloadAnimation方法开始加载动画,首先去查询动画文件,动画文件的存放位置如代码中定义所示。动画文件是按照指定位置顺序读取,如果读取到当前位置动画文件,则不读取后续动画文件。
源码路径:frameworks/base/cmds/bootanimation/BootAnimation.cpp
static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
static const char PRODUCT_BOOTANIMATION_DARK_FILE[] = "/product/media/bootanimation-dark.zip";
static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
static const char APEX_BOOTANIMATION_FILE[] = "/apex/com.android.bootanimation/etc/bootanimation.zip";
static const char PRODUCT_ENCRYPTED_BOOTANIMATION_FILE[] = "/product/media/bootanimation-encrypted.zip";
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
static const char PRODUCT_SHUTDOWNANIMATION_FILE[] = "/product/media/shutdownanimation.zip";
static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip";static constexpr const char* PRODUCT_USERSPACE_REBOOT_ANIMATION_FILE = "/product/media/userspace-reboot.zip";
static constexpr const char* OEM_USERSPACE_REBOOT_ANIMATION_FILE = "/oem/media/userspace-reboot.zip";
static constexpr const char* SYSTEM_USERSPACE_REBOOT_ANIMATION_FILE = "/system/media/userspace-reboot.zip";BootAnimation::BootAnimation(sp<Callbacks> callbacks): Thread(false), mLooper(new Looper(false)), mClockEnabled(true), mTimeIsAccurate(false),mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {mSession = new SurfaceComposerClient();std::string powerCtl = android::base::GetProperty("sys.powerctl", "");if (powerCtl.empty()) {mShuttingDown = false;} else {mShuttingDown = true;}ALOGD("%sAnimationStartTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",elapsedRealtime());
}
void BootAnimation::onFirstRef() {//接收SurfaceFlinger死亡通知status_t err = mSession->linkToComposerDeath(this);SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));if (err == NO_ERROR) {// Load the animation content -- this can be slow (eg 200ms)// called before waitForSurfaceFlinger() in main() to avoid waitALOGD("%sAnimationPreloadTiming start time: %" PRId64 "ms",mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());preloadAnimation();ALOGD("%sAnimationPreloadStopTiming start time: %" PRId64 "ms",mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());}
}
bool BootAnimation::preloadAnimation() {findBootAnimationFile();if (!mZipFileName.isEmpty()) {//加载动画mAnimation = loadAnimation(mZipFileName);return (mAnimation != nullptr);}return false;
}
void BootAnimation::findBootAnimationFile() {// If the device has encryption turned on or is in process// of being encrypted we show the encrypted boot animation.char decrypt[PROPERTY_VALUE_MAX];property_get("vold.decrypt", decrypt, "");bool encryptedAnimation = atoi(decrypt) != 0 ||!strcmp("trigger_restart_min_framework", decrypt);if (!mShuttingDown && encryptedAnimation) {static const std::vector<std::string> encryptedBootFiles = {PRODUCT_ENCRYPTED_BOOTANIMATION_FILE, SYSTEM_ENCRYPTED_BOOTANIMATION_FILE,};if (findBootAnimationFileInternal(encryptedBootFiles)) {return;}}const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1;static const std::vector<std::string> bootFiles = {APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE,OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};static const std::vector<std::string> shutdownFiles = {PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE, ""};static const std::vector<std::string> userspaceRebootFiles = {PRODUCT_USERSPACE_REBOOT_ANIMATION_FILE, OEM_USERSPACE_REBOOT_ANIMATION_FILE,SYSTEM_USERSPACE_REBOOT_ANIMATION_FILE,};if (android::base::GetBoolProperty("sys.init.userspace_reboot.in_progress", false)) {findBootAnimationFileInternal(userspaceRebootFiles);} else if (mShuttingDown) {findBootAnimationFileInternal(shutdownFiles);} else {findBootAnimationFileInternal(bootFiles);}
}
bool BootAnimation::findBootAnimationFileInternal(const std::vector<std::string> &files) {for (const std::string& f : files) {if (access(f.c_str(), R_OK) == 0) {mZipFileName = f.c_str();return true;}}return false;
}
BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) {if (mLoadedFiles.indexOf(fn) >= 0) {SLOGE("File \"%s\" is already loaded. Cyclic ref is not allowed",fn.string());return nullptr;}ZipFileRO *zip = ZipFileRO::open(fn);if (zip == nullptr) {SLOGE("Failed to open animation zip \"%s\": %s",fn.string(), strerror(errno));return nullptr;}ALOGD("%s is loaded successfully", fn.string());Animation *animation = new Animation;animation->fileName = fn;animation->zip = zip;animation->clockFont.map = nullptr;mLoadedFiles.add(animation->fileName);//解析动画文件parseAnimationDesc(*animation);if (!preloadZip(*animation)) {releaseAnimation(animation);return nullptr;}mLoadedFiles.remove(fn);return animation;
}
bool BootAnimation::parseAnimationDesc(Animation& animation) {String8 desString;if (!readFile(animation.zip, "desc.txt", desString)) {return false;}char const* s = desString.string();std::string dynamicColoringPartName = "";bool postDynamicColoring = false;// Parse the description file...
}
bootanimation.zip
动画文件的压缩包里都存在一个动画配置文件desc.txt,它是描述开机动画是如何显示的。我们以device/google/atv/products/bootanimations/bootanimation.zip动画压缩包为例进行分析,它是AndroidTV存储动画文件的路径。desc.txt内容如下:
第1行用来描述开机动画在屏幕显示的大小及帧率。这个定义指示 bootanimation 的播放分辨率为 512x416 像素,帧率为 60 帧/秒。分辨率定义了动画的宽度和高度,而帧率定义了动画播放的流畅程度,即每秒播放的帧数。
第2行c:表示清除命令。1:表示清除的起始帧。0:表示清除的结束帧。part0:表示需要清除的动画帧所在的文件夹路径。这个定义指示在播放动画时,从指定的文件夹 part0 中清除第 1 帧。这样可以控制在播放过程中是否清除特定的帧,以实现动画效果的变化或平滑的过渡效果。3-5行同理。
最后一行f:表示循环命令。0:表示循环的起始帧。0:表示循环的结束帧。part4:表示需要循环的动画帧所在的文件夹路径。10:表示循环次数。该行指示在播放动画时,从指定的文件夹中的起始帧到结束帧之间的帧进行循环播放,重复播放 10 次。
512 416 60
c 1 0 part0
c 1 15 part1
c 1 0 part2
c 1 0 part3
f 0 0 part4 10
动画配置文件还有指定播放顺序的,例如如下的配置,p:表示播放顺序命令。1:表示播放的顺序。0:表示播放的循环次数。0 表示无限循环。folder1:表示动画帧所在的文件夹路径。根据这个定义,folder1 是一个目录,包含了一组 bootanimation 动画帧文件。该行指示在播放动画时,按照顺序从 folder1 目录中加载帧并进行播放。
p 1 0 folder1
加载动画执行完成后,接下来会执行主体函数threadLoop,首先判断自定义开机动画文件是否存在,如果不存在则执行Android方法,否则执行自定义动画Movie方法。Android和Movie方法最后都返回false。因此threadloop也返回false,代表代码只执行一次。最后获取service.bootanim.exit属性,如果值为1,循环就会退出,开机动画就会结束。service.bootanim.exit属性是在AMS中被修改为1的,在后面AMS中会讲到。
static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
bool BootAnimation::threadLoop() {bool result;initShaders();// We have no bootanimation file, so we use the stock android logo// animation.if (mZipFileName.isEmpty()) {ALOGD("No animation file");//系统默认开机画面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::android() {glActiveTexture(GL_TEXTURE0);SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",elapsedRealtime());//android-logo-mask.png和android-logo-shine.png保存在frameworks/base/core/res/assets/images/路径下initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");mCallbacks->init({});...return false;
}
bool BootAnimation::movie() {if (mAnimation == nullptr) {mAnimation = loadAnimation(mZipFileName);}if (mAnimation == nullptr)return false;...playAnimation(*mAnimation);releaseAnimation(mAnimation);mAnimation = nullptr;return false;
}
bool BootAnimation::playAnimation(const Animation& animation) {...checkExit();
}
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();}
}
总结
init进程是Android系统中的第一个用户空间进程。它负责启动各个系统服务和应用程序。在init进程启动过程中,SurfaceFlinger也被启动,SurfaceFlinger是Android中的显示系统服务,负责管理屏幕显示和图形渲染。开机动画需要使用SurfaceFlinger来显示。然后bootanimation也启动,进行开机动画的播放。bootanimation.zip中包含动画文件和动画配置文件。最终,当所有系统服务和应用程序启动完毕,开机动画结束,进入系统主界面。
相关文章:

Android开机动画启动流程
首语 在Android设备开机启动时,会展示Android开机动画,用于增加用户体验和展示设备品牌等信息。它也是Android系统启动的一部分。开机动画是由bootanimation负责的,因此首先先了解下bootanimation是如何启动的。 bootanimation 启动脚本分析…...

react_13
React Router //-dom代表给浏览器应用使用的 npm install react-router-dom 目前版本是 "react-router-dom": "^6.18.0" 使用 新建文件 src/router/MyRouter.tsx import { Navigate, RouteObject, useRoutes } from "react-router-dom"; imp…...

vscode git提交
...

LangChain+LLM实战---实用Prompt工程讲解
原文:Practical Prompt Engineering 注:本文中,提示和prompt几乎是等效的。 这是一篇非常全面介绍Prompt的文章,包括prompt作用于大模型的一些内在机制,和prompt可以如何对大模型进行“微调”。讲清楚了我们常常听到的…...

虚拟机备份中的CBT技术
虚拟机备份的CBT( Changed Block Tracking)模式是一种备份模式,它能够识别和跟踪自上次备份后虚拟机中被修改过的块,这些修改会被存放到日志文件中。在启用CBT模式之后,备份软件会利用这个功能进行增量备份。 启用CBT…...

云服务器哪家便宜靠谱 | 简单了解亚马逊云科技发展史
云服务器哪家便宜又靠谱呢?为什么说亚马逊云科技在这道题答案的第一行,一篇故事告诉你。 1994年,杰夫贝索斯在西雅图创建了亚马逊,最初只是一个在线书店。 1997年,亚马逊在纳斯达克交易所上市,成为一家公…...

【LeetCode】每日一题 2023_11_6 最大单词长度乘积
文章目录 刷题前唠嗑题目:最大单词长度乘积题目描述代码与解题思路偷看大佬题解 结语 刷题前唠嗑 LeetCode? 启动!!! 题目:最大单词长度乘积 题目链接:318. 最大单词长度乘积 题目描述 代码与解题思路…...

【小白专用】PHP中的JSON转换操作指南 23.11.06
一、JSON的基础知识 1.1JSON数据格式 JSON数据格式是一组键值对的集合,通过逗号分隔。键值对由“键”和“值”组成,中间使用冒号分隔。JSON数据格式可以嵌套,而且可以使用数组 二、PHP中的JSON函数 JSON的操作需要使用编程语言进行处理&am…...

Web3游戏的十字路口:沿用传统IP还是另起炉灶?
人们经常问我对 Web3 游戏有什么看法。因此,我想以书面形式概述一下我目前的想法。 让我先澄清一下:我不是专家。这不是一篇深入探讨游戏世界精细指标如 MAU 或 D14 等的全面分析。请把这看作是我根据个人交流和研究,这反映我在游戏领域关注…...

【系统架构设计】架构核心知识:4 系统可靠性分析与设计
目录 1 可靠性 2 系统可靠性 2.1 可靠性指标 2.2 可靠性计算 2.2.1 串联系统 2.2.2 并联系统</...

什么是站群服务器的优点?
什么是站群服务器的优点? 1. 主要作用 在网站数量增多的今天,对于站群服务器的需求自然也会变得越来越多,那么,它的主要作用都是什么呢?站群服务器,就好像它的名字一样,是一个群体,…...

图数据库Neo4j——SpringBoot使用Neo4j 简单增删改查 复杂查询初步
前言 图形数据库是专门用于存储图形数据的数据库,它使用图形模型来存储数据,并且支持复杂的图形查询。常见的图形数据库有Neo4j、OrientDB等。 Neo4j是用Java实现的开源NoSQL图数据库,本篇博客介绍如何在SpringBoot中使用Neo4j图数据库&…...

-- Could NOT find livox_ros_driver (missing: livox_ros_driver_DIR)
原因 缺少livox_ros_driver 包 解决办法如下 livox_ros_driver 地址 https://github.com/Livox-SDK/livox_ros_driver 下载下来放入ros的工作目录...

山东餐饮类行业可以办理那些认证?
在招投标中很多企业会因为缺少一些证书从而丢失加分项,所以很多行业都会关注那些针对性比较强的企业认证,今天就来讲一下餐饮类行业招投标有哪些证书可以帮助企业中标? 一、ISO三体系认证 ISO9001 质量管理体系 质量是取得成功的关键。由…...

【抖音自动评论的软件】评论888无偿分享,和其开发技术与开发流程的分享
先来看成果,↑↑需要的同学可看我名字↖↖↖↖↖,或评论888无偿分享 短视频作为互联网时代的重要产物,已经成为人们生活中不可或缺的一部分。那么,如何通过短视频平台进行有效的运营和评论呢?本文将为您详细解析。 一…...

挑战100天 AI In LeetCode Day02(2)
挑战100天 AI In LeetCode Day02(2) 一、LeetCode介绍二、LeetCode 热题 HOT 100-42.1 题目2.2 题解 三、面试经典 150 题-43.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站,提供各种算法和数据结构的题目,面向程序…...

《尚医通》Vue3 项目+TypeScript 前端项目(持续更新,附带源码)
尚硅谷vue项目实战《尚医通》,Vue3项目TypeScript前端项目_哔哩哔哩_bilibili尚硅谷vue项目实战《尚医通》,Vue3项目TypeScript前端项目共计71条视频,包括:001_开篇介绍、002_尚医通项目的简介、003_Vite构建化工具初始化项目等&a…...

仪表盘 gauge
option {tooltip: {formatter: {a} <br/>{b} : {c}%},series: [{name: Pressure,type: gauge,startAngle: 225, // 起始角度,同极坐标endAngle: -45, // 终止角度,同极坐标// axisLine: {// //坐标轴轴线// show: false// },// splitLine: {//…...

常见面试题-MySQL专栏(三)MVCC、BufferPool
typora-copy-images-to: imgs 了解 MVCC 吗? 答: MVCC(Multi-Version Concurrency Control) 是用来保证 MySQL 的事务隔离性的,对一行数据的读和写两个操作默认是不会通过加锁互斥来保证隔离性,避免了频…...

CDN加速:国内外价格与企业云服务最佳搭配方案
随着互联网的快速发展,CDN(内容分发网络)已经成为了企业提供高质量、高速度内容传递的不可或缺的工具。CDN通过将内容分发到离用户更近的服务器上,提高了网站性能,减少了加载时间,改善了用户体验。在本文中…...

uni-app小程序使用vant
步骤一:安装 Vant Weapp # 通过 npm 安装 npm i vant/weapp -S --production# 通过 yarn 安装 yarn add vant/weapp --production# 安装 0.x 版本 npm i vant-weapp -S --production步骤二:在根目录下创建“wxcomponents”文件夹 步骤三:找…...

C-DS二叉树_另一棵树的子树
Description 给你两棵二叉树tree1和tree2,检验tree1中是否包含和tree2具有相同结构和结点值的子树。如果存在,输出true;否则,输出false。 Input 第一行输入t,表示有t个测试样例。 第二行首先输入n1,接着输入n1个整数,表示二叉树tree1。 第三行首先输入n2,接着输入n…...

祝贺璞华大数据产品入选中国信通院“铸基计划”
武汉璞华大数据技术有限公司HawkEye设备数字化管理平台产品,凭借优秀的产品技术能力,通过评估后,入选中国信通院“铸基计划”《高质量数字化转型产品及服务全景图(2023)》的工业数字化领域。 “铸基计划”是中国信通院推出的高质量…...

WebDAV之π-Disk派盘 + MiXplorer
MiXplorer是一款非常强大实用的手机文档管理器,能给用户提供了一系列的文档处理功能,包括本地文件浏览、文件排序、文件筛选、切换视图、新建文件、添加收藏等等,同时还能将你手机里的所有文件都罗列出来,简洁明了,让用户一眼就能够找到相应的文件并对其进行编辑,或是删除…...

java依赖的jar包下载
不需要依赖maven,直接下载jar。 仓库服务...

苹果加大对印度的扶持,提高在其生产iphone的比重
KlipC报道:跟踪苹果产业链,有分析师预计2023年全球约12%-14%的iphone在印度生产,预计2024年,印度将生产20%-25%的iphone。 KlipC的合伙人Andi D表示:“近年来随着苹果对中国的以来,印度已经成为高科技制造和…...

【漏洞复现】typecho_v1.0-14.10.10_unserialize
感谢互联网提供分享知识与智慧,在法治的社会里,请遵守有关法律法规 文章目录 漏洞利用GetShell 下载链接:https://pan.baidu.com/s/1z0w7ret-uXHMuOZpGYDVlw 提取码:lt7a 首页 漏洞点:/install.php?finish 漏洞利用 …...

Linux常见面试题
1、 冯诺依曼体系的要点是: 数字计算机的数制采用二进制,bit 位, byte 字节 1 byte 8 bit计算机应该按照程序顺序执行计算机硬件由运算器、控制器、存储器、输入设备和输出设备五大部分组成 2、计算机的硬件五个组件 控制器: 指挥系统运算器: 数学和逻…...

HarmonyOS ArkTS基础知识
概述 上一节,学习了TypeScript的基础语法,而在鸿蒙开发当中,有基于自己的编程语言,便是ArkTS。它是一种声明式UI的编程范式的语言,开发框架如下图所示: 根据框架图,分析,我将它大致…...

嵌入式课后习题第一章解答
嵌入式系统是一种以应用为中心,以计算机技术为基础,软/硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机。它与通用PC的区别主要体现在以下几个方面: 应用针对性:嵌入式系统是专为特定应…...