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

个性化网站开发/自己做网站的流程

个性化网站开发,自己做网站的流程,烟台做网站多钱,合肥做网站专家此前大部分涉及到 RecyclerView 页面的 LayoutManager基本上用系统提供的 LinearLayoutManager 、GridLayoutManager 就能解决,但在一些特殊场景上还是需要我们自定义 LayoutManager。之前基本上没有自己写过,在网上看各种源码各种文章,刚开始…

此前大部分涉及到 RecyclerView 页面的 LayoutManager基本上用系统提供的 LinearLayoutManager 、GridLayoutManager 就能解决,但在一些特殊场景上还是需要我们自定义 LayoutManager。之前基本上没有自己写过,在网上看各种源码各种文章,刚开始花了好多时间去理解整体流程,因为它们都给我一种非常非常复杂的感觉,包括相关的博客文章也是。经过一段时间摸索,也慢慢能理解为什么要那么复杂了,这的确不是特别容易入门。所以对整体的流程进行了一个拆解,尽量原子化一点,对自己学习的一个总结,也希望能帮助到一部分人能对 LayoutManager 入门。

本文最终实现一个简单的 LinearLayoutManager(只支持 VERTICAL)方向,适合对 LayoutManager 整体流程的学习与理解,整体代码分为多个文件,每个文件都是对前一段代码的补充,方便理解,整体项目源码已提交 Github: LayoutManagerGradually,代码里面写了很多很多注释,如果不想浪费时间,可以直接看代码运行,跳过这篇文章,把每一个 LayoutManager 都跑一下体验结合代码看看。

自定义 LayoutManager 的必要元素

  • 继承 RecyclerView.LayoutManager 并实现 generateDefaultLayoutParams() 方法

  • 重写onLayoutChildren 第一次数据填充的时候数据添加

  • 重写 canScrollHorizontally()canScrollVertically()方法设定支持滑动的方向

  • 重写 scrollHorizontallyBy()scrollVerticallyBy()方法,在滑动的时候对屏幕以外的 View 进行回收,以及填充即将滑动进入屏幕范围内的 View 进行填充

  • 重写 scrollToPosition()smoothScrollToPosition()方法支持

其中onLayoutChildrenscrollHorizontallyBy/scrollVerticallyBy 是最核心且最复杂的方法,这里稍微拎出来讲一下

onLayoutChildren

这个方法类似于自定义 ViewGroup 的 onLayout() 方法,RecyclerView 的 LayoutManager.onLayoutChildren 在以下几个时机会被触发:

  • RecyclerView 首次附加到窗口时
  • Adapter 的数据集发生变化
  • RecyclerView 被 执行 RequetLayout的时候
  • LayoutManager 发生变化时

scrollHorizontallyBy/scrollVerticallyBy

方法的主要作用包括:

  1. 更新 ItemView 的位置:根据传入的垂直滚动距离(dy 参数),更新子视图在屏幕上的位置。通常调用 offsetChildrenVertical 方法。

  2. 回收不可见的 ItemView:在滚动过程中,一些 ItemView 可能会离开屏幕,变得不可见。scrollVerticallyBy 方法需要负责回收这些子视图并将它们放入回收池,以便稍后复用。

  3. 添加新的 ItemView:在滚动过程中,新的 ItemView 可能需要显示在屏幕上。scrollVerticallyBy 方法需要从回收池中获取可复用的视图并将它们添加到屏幕上。这通常涉及到调用 RecyclerView.RecyclergetViewForPosition 方法。

  4. 返回实际滚动距离:由于 ItemView 的数量有限,滚动可能会受到限制。例如,当滚动到列表顶部或底部时,滚动可能会停止。在这种情况下,实际滚动的距离可能会小于传入的 dy 参数。scrollVerticallyBy 方法需要返回实际滚动的距离,以便 RecyclerView 可以正确地更新滚动条和触发滚动事件。

概念就简单讲这么多, talk is cheap show me the code,直接看代码理解会比较深刻

逐步实现

要实现一个可用的 LayoutManger 通常我们需要实现以下流程

  • 数据填充并且只需要填充屏幕范围内的 ItemView
  • 回收掉屏幕以外的 ItemView
  • 屏幕外 ItemView 再回到屏幕后,需要重新填充
  • 对滑动边界边界进行处理
  • 对 scrollToPosition 和 smoothScrollToPosition进行支持

我们不用一上来就实现最终的效果,而是一步一步来,看看 LayoutManger 是怎么渐渐地变化,最终能跑起来的。

0 最简单的 LayoutManager

代码查看:MostSimpleLayoutManager,我们关注 onLayoutChildren 方法:

override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State?) {// 垂直方向的偏移量var offsetTop = 0// 实际业务中最好不要这样一次性加载所有的数据,这里只是最简单地演示一下整体是如何工作的for (itemIndex in 0 until itemCount) {// 从适配器获取与给定位置关联的视图val itemView = recycler.getViewForPosition(itemIndex)// 将视图添加到 RecyclerView 中addView(itemView)// 测量并布局视图measureChildWithMargins(itemView, 0, 0)// 拿到宽高(包括ItemDecoration)val width = getDecoratedMeasuredWidth(itemView)val height = getDecoratedMeasuredHeight(itemView)// 对要添加的子 View 进行布局layoutDecorated(itemView, 0, offsetTop, width, offsetTop + height)offsetTop += height}
}

上面的代码主要演示了,如何利用addView layoutDecorated等方法,将 ItemView 添加到 RecyclerView 上。代码可见是 将所有的 ItemView(即使它在屏幕上不可见)一次性全部加载到了 RecyclerView上, 这里一般不这么做,只是这里这里只是最简单地演示一下整体是如何工作的。

运行在手机上能看到这样的效果:Item数据已经被全部添加到界面上了,并且各个方向的滑动都支持。

1 更合理的数据添加方式

代码查看:LinearLayoutManager1.kt

对最开始的代码进行优化,只在屏幕范围内的区域进行数据的添加,这样就不需要一次性将所有数据就添加上去,如果 Adapter 的 ItemCount 足够巨大,for all addView 的话,很容易就 OOM。

override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {// 垂直方向上的的空间大小var remainSpace = height - paddingTop//垂直方向的偏移量var offsetTop = 0var currentPosition = 0while (remainSpace > 0 && currentPosition < state.itemCount) {// 从适配器获取与给定位置关联的视图val itemView = recycler.getViewForPosition(currentPosition)// 将视图添加到 RecyclerView 中addView(itemView)// 测量并布局视图measureChildWithMargins(itemView, 0, 0)// 拿到宽高(包括ItemDecoration)val itemWidth = getDecoratedMeasuredWidth(itemView)val itemHeight = getDecoratedMeasuredHeight(itemView)// 对要添加的子 View 进行布局layoutDecorated(itemView, 0, offsetTop, itemWidth, offsetTop + itemHeight)offsetTop += itemHeightcurrentPosition++// 可用空间减少remainSpace -= itemHeight}
}

2 对屏幕外的View回收

代码查看:LinearLayoutManager2

RecylerView 没有 recycler 怎么行呢?当 RecylerView 的 ItemView 滑出屏幕后我们需要对齐进行回收,实现的话需要在 scrollVerticallyBy中,比较复杂的逻辑就是怎么去判断:ItemView 在屏幕以外,最后利用:removeAndRecycleView方法进行回收

override fun scrollVerticallyBy(dy: Int, recycler: RecyclerView.Recycler, state: RecyclerView.State?): Int {// 在这里处理上下的滚动逻辑,dy 表示滚动的距离// 平移所有子视图offsetChildrenVertical(-dy)// 如果实际滚动距离与 dy 相同,返回 dy;如果未滚动,返回 0recycleInvisibleView(dy, recycler)return dy
}/*** 回收掉在界面上看不到的 ItemView** @param dy* @param recycler*/
private fun recycleInvisibleView(dy: Int, recycler: RecyclerView.Recycler) {val totalSpace = orientationHelper.totalSpace// 将要回收View的集合val recycleViews = hashSetOf<View>()// 从下往上滑if (dy > 0) {for (i in 0 until childCount) {val child = getChildAt(i)!!// 从下往上滑从最上面的 item 开始计算val top = getDecoratedTop(child)// 判断最顶部的 item 是否已经完全不可见,如何可见,那说明底下的 item 也是可见val height = top - getDecoratedBottom(child)if (height - top < 0) {break}recycleViews.add(child)}} else if (dy < 0) {   // 从上往下滑for (i in childCount - 1 downTo 0) {val child = getChildAt(i)!!// 从上往下滑从最底部的 item 开始计算val bottom = getDecoratedBottom(child)// 判断最底部的 item 是否已经完全不可见,如何可见,那说明上面的 item 也是可见val height = bottom - getDecoratedTop(child)if (bottom - totalSpace < height) {break}recycleViews.add(child)}}// 真正把 View 移除掉的逻辑for (view in recycleViews) {// [removeAndRecycleView]// 用于从视图层次结构中删除某个视图,并将其资源回收,以便在需要时重新利用removeAndRecycleView(view, recycler)}recycleViews.clear()
}

运行在手机上能看到这样的效果:滑出屏幕外的ItemView 被回收掉了

3 向上滑动的时View的填充

代码查看:LinearLayoutManager3

override fun scrollVerticallyBy(dy: Int, recycler: RecyclerView.Recycler, state: RecyclerView.State?): Int {// 填充 viewfillView(dy, recycler)// 移动 viewoffsetChildrenVertical(-dy)// 回收 ViewrecycleInvisibleView(dy, recycler)return dy
}/*** 填充重新进入屏幕内的 ItemView*     getChildCount():childCount-> 当前屏幕内RecyclerView展示的 ItemView 数量*     getItemCount():itemCount-> 最大的 ItemView 数量,也就是 Adapter 传递的数据的数量*/
private fun fillView(dy: Int, recycler: RecyclerView.Recycler) {val verticalSpace = orientationVerticalHelper.totalSpacevar remainSpace = 0var nextFillPosition = 0//垂直方向的偏移量var offsetTop = 0var offsetLeft = 0// 从下往上滑,那么需要向底部添加数据if (dy > 0) {val anchorView = getChildAt(childCount - 1) ?: returnval anchorPosition = getPosition(anchorView)val anchorBottom = getDecoratedBottom(anchorView)val anchorLeft = getDecoratedLeft(anchorView)remainSpace = verticalSpace - anchorBottom// 垂直可用的数据为<0,意外着这时候屏幕底部的位置刚好在最底部的 ItemView 上,还需要向上滑动一点点...我们才能添加 Viewif (remainSpace < 0) {return}nextFillPosition = anchorPosition + 1offsetTop = anchorBottomoffsetLeft = anchorLeftif (nextFillPosition >= itemCount) {return}} else if (dy < 0) {  // 从上往下滑,那么需要向顶部添加数据//no-op 暂时不实现从上往下滑的底部数据填充}while (remainSpace > 0 && nextFillPosition < itemCount) {// 从适配器获取与给定位置关联的视图val itemView = recycler.getViewForPosition(nextFillPosition)// 将视图添加到 RecyclerView 中addView(itemView)// 测量并布局视图measureChildWithMargins(itemView, 0, 0)// 拿到宽高(包括ItemDecoration)val itemWidth = getDecoratedMeasuredWidth(itemView)val itemHeight = getDecoratedMeasuredHeight(itemView)// 对要添加的子 View 进行布局,相比onLayoutChildren 里面的实现添加了:offsetLeft(因为我们没有禁止掉 左右的滑动)// 试着把 offsetLeft 改成0,也就是最原始的样子,然后左右上下滑滑,你会有意外收获layoutDecorated(itemView, offsetLeft, offsetTop, itemWidth + offsetLeft, offsetTop + itemHeight)offsetTop += itemHeightnextFillPosition++// 可用空间减少remainSpace -= itemHeight}
}

运行在手机上能看到这样的效果:向上滑动的时候,底部陆续有元素填充,但向下滑动的时候没有填充数据

4 两个方向的View填充

代码查看:LinearLayoutManager4

补齐从上往下滑之后添加的逻辑

private fun fillView(dy: Int, recycler: RecyclerView.Recycler) {val verticalSpace = orientationVerticalHelper.totalSpacevar remainSpace = 0var nextFillPosition = 0//垂直方向的偏移量var offsetTop = 0var offsetLeft = 0// 从下往上滑,那么需要向底部添加数据if (dy > 0) {……} else if (dy < 0) {  // 从上往下滑,那么需要向顶部添加数据val anchorView = getChildAt(0) ?: returnval anchorPosition = getPosition(anchorView)val anchorTop = getDecoratedTop(anchorView)offsetLeft = getDecoratedLeft(anchorView)remainSpace = anchorTop// 垂直可用的数据为<0,意外着这时候屏幕顶部的位置刚好在最底部的 ItemView 上,还需要向下滑动一点点...我们才能添加 Viewif (anchorTop < 0) {return}nextFillPosition = anchorPosition - 1if (nextFillPosition < 0) {return}val itemHeight = getDecoratedMeasuredHeight(anchorView)// 新的布局的itemView 的顶部位置应该以 anchorTop - itemHeight 开始offsetTop = anchorTop - itemHeight}while (remainSpace > 0 &&((nextFillPosition < itemCount) && (nextFillPosition >= 0))) {// 从适配器获取与给定位置关联的视图val itemView = recycler.getViewForPosition(nextFillPosition)// 将视图添加到 RecyclerView 中k,从顶部添加的话,需要加到最前的位置if (dy > 0) {addView(itemView)} else {addView(itemView, 0)}……if (dy > 0) {offsetTop += itemHeightnextFillPosition++} else {offsetTop -= itemHeightnextFillPosition--}// 可用空间减少remainSpace -= itemHeight}

运行在手机上能看到这样的效果:向上或者滑动的时候,底部陆续都有元素填充

5 对顶部和底部滑动边界处理

代码查看:LinearLayoutManager5

对于前面的实现会发现会:不停地下滑或者上滑会留出来巨大的空白。这里对填充 View 的逻辑进行改造,需要进行边界检测。

override fun scrollVerticallyBy(dy: Int, recycler: RecyclerView.Recycler, state: RecyclerView.State?): Int {// 填充 viewval adjustedDy = fillView(dy, recycler)// 移动 viewoffsetChildrenVertical(-adjustedDy)// 回收 ViewrecycleInvisibleView(adjustedDy, recycler)// 由于需要对边界进行限制,所以需要对原始的 dy 进行修正,这里不再直接返回 dyreturn adjustedDy
}

这里的整体注释我写在了代码里面,可以看图稍微理解一下,以向上滑动为例:假设这一次滑动的距离非常非常大(想象成10000像素),如果直接滑动的话,我们有50个元素,每个元素高度100像素,最大高度也只有50x100=5000,那么滑动后一定会留下大量空区域。需要对当前传入的这 10000 像素做调整:只给到可滑动的最大距离,如果不能滑动了就返回0。

运行在手机上能看到这样的效果:向上或者滑动的时候,达到最大的位置时候是不能再滑动的。

6 实现 scrollToPosition

代码查看:LinearLayoutManager6

到这里这个 LinearLayoutManager 看着已经能正常运行了,但一般还需要支持scrollToPositionsmoothScrollToPositio

private var mPendingScrollPosition = RecyclerView.NO_POSITIONoverride fun scrollToPosition(position: Int) {super.scrollToPosition(position)if (position < 0 || position >= itemCount) {return}mPendingScrollPosition = positionrequestLayout()
}override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {……var currentPosition = 0if (mPendingScrollPosition != RecyclerView.NO_POSITION) {currentPosition = mPendingScrollPosition}while (remainSpace > 0 && currentPosition < state.itemCount) {…… // 填充View 的逻辑}
}

scrollToPosition 的实现比较简单,如上代码所示:在 scrollToPosition 的时候记录一次目标position,再 requestLayout 一波,还记得之前有提到过:onLayoutChildren 会在 requestLayout 的时候调用一次,于是再将onLayoutChildren逻辑改写,不再从第0个元素开始,而是从目标位置进行布局。

运行在手机上能看到这样的效果:点击 scrollTo30 将会滑动到 第30个位置。

7 实现 smoothScrollToPosition

代码查看:LinearLayoutManager7

要实现自定义的 smoothScrollToPosition 动画效果,这一块如果要完全自己实现的话比较复杂,可以直接使用系统提供的 LinearSmoothScroller改造,也可以继承 RecyclerView.SmoothScroller 自定义,也可以完全不使用 SmoothScroller, 照着 SmoothScroller 的实现使用类似 ValueAnimator 自定义动画,添加动画 UpdateListener,在 onAnimationUpdate 的时候动态计算布局从而实现滑动动画,这里拿 LinearSmoothScroller 举例:

override fun smoothScrollToPosition(recyclerView: RecyclerView,state: RecyclerView.State,position: Int
) {if (position >= itemCount || position < 0) {return}val scroller: LinearSmoothScroller = object : LinearSmoothScroller(recyclerView.context) {/*** 这个方法用于计算滚动到目标位置所需的滚动向量。滚动向量是一个二维向量,包含水平和垂直方向上的滚动距离** @param targetPosition 滑动的目标位置* @return  返回一个 PointF 对象,表示滚动向量。*              PointF.x 表示水平方向上的滚动距离,*              PointF.y 表示垂直方向上的滚动距离*/override fun computeScrollVectorForPosition(targetPosition: Int): PointF {// 查找到屏幕里显示的第 1 个元素与val firstChildPos = getPosition(getChildAt(0)!!)val direction = if (targetPosition < firstChildPos) -1 else 1// x 左右滑动,由于我们只实现了垂直的滑动,所以 x方向为0即可// 整数代表正向移动,负数代表反向移动,这里的数值大小不重要,源码里面最终都会 normalize 归一化处理return PointF(0f, direction.toFloat())}/*** 计算每像素速度** @param displayMetrics* @return 返回每一像素的耗时,单位ms,假设返回值是1.0 代表着:1ms 内会滑动 1像素,1s会滑动1000像素*/override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics?): Float {return super.calculateSpeedPerPixel(displayMetrics)}/*** 滑动速度的插值(实现滑动速度随着滑动时间的变化)** @param dx* @return*/override fun calculateTimeForDeceleration(dx: Int): Int {return super.calculateTimeForDeceleration(dx)}// 很多方法可以使用,不再一一列举// ...}scroller.targetPosition = position// 执行默认动画的逻辑startSmoothScroll(scroller)
}

运行在手机上能看到这样的效果:点击 smoothScrollTo30 将会有个动画效果滑动到第30个位置。

以上基本上一个自定义 LayoutManager 的雏形就已经完成了,虽然只实现了一个方向的滑动,但是其原理都是一样的,剩下的就是各种细节的打磨了,可以加各种自己想要的效果,比如:指定位置 放大一定的系数,或者更炫酷的滑动动画…

总结

本文主要整理了自定义 LayoutManager 的必要元素,以及其核心方法 scrollHorizontallyBy/scrollVerticallyBy、onLayoutChildren 的作用与调用时机,接下对实现一个简单的 LinearLayoutManger 进行逻辑拆解,从最简单的不滑动回收和填充以及不含滑动边界检测,到最终一个具备基本功能的 LinearLayoutManger

源码:https://github.com/VomPom/LayoutManagerGradually

参考:

《看完这篇文章你还不会自定义LayoutManager,我吃X!》

《/LayoutManager分析与实践》

Building a RecyclerView LayoutManager – Part 1

相关文章:

RecyclerView自定义LayoutManager从0到1实践

此前大部分涉及到 RecyclerView 页面的 LayoutManager基本上用系统提供的 LinearLayoutManager 、GridLayoutManager 就能解决&#xff0c;但在一些特殊场景上还是需要我们自定义 LayoutManager。之前基本上没有自己写过&#xff0c;在网上看各种源码各种文章&#xff0c;刚开始…...

【虹科干货】5个关于微服务的误解

你认为微服务架构能为你带来什么&#xff1f;难道微服务真的是一劳永逸的吗&#xff1f;又或者&#xff0c;难道微服务的威力并不如传闻所言&#xff1f;微服务架构应当如何设计才能真正彰显它作为一种解决方案的好处呢&#xff1f; 文章速览&#xff1a; 误解一&#xff1a;…...

利用卷影拷贝服务攻击域控五大绝招

点击星标&#xff0c;即时接收最新推文 在微软Active Directory&#xff08;活动目录&#xff09;中&#xff0c;所有的数据都被保存在ntds.dit中&#xff0c; NTDS.DIT是一个二进制文件&#xff0c; 它存在于域控制器中的 %SystemRoot%\ntds\NTDS.DIT。ntds.dit包括但不限于Us…...

web3 在React dapp中全局管理web3当前登录用户/智能合约等信息

上文 Web3 React项目Dapp获取智能合约对象我们在自己的前端dapp项目中链接获取到了 自己的智能合约 我们继续 我们还是先启动ganache环境 终端输入 ganache -d然后发布一下我们的智能合约 打开我们的合约项目 终端输入 truffle migrate --reset这样 我们的智能合约就部署到区…...

Golang硬件控制:将软件力量扩展到物理世界

引言 在过去的几十年中&#xff0c;计算机科学和软件工程领域取得了巨大的发展和进步。现在&#xff0c;我们可以编写各种强大的软件应用程序来解决各种问题。然而&#xff0c;软件并不仅限于在计算机上运行&#xff0c;它也可以扩展到物理世界中。这就是Golang的魅力所在。Go…...

Docker 查看Image镜像的Dockerfile方法

1、创建测试镜像 Dockerfile: FROM centos LABEL maintainer"NGINX Docker Maintainers docker-maintnginx.com" RUN yum install -y nginx RUN echo "Nginx Web: CMD defining default arguments for an ENTRYPOINT" > /usr/share/nginx/html/index.…...

el-dialog中嵌套iframe之后拿不到iframe的id 的解决办法

在vueelement项目中想用到el-dialog弹窗加iframe嵌套外部页面的方法,但是这时候要获取iframe里面的ID 但是这时候怎么也获取不到 <el-dialog ref"middleFlag" v-if"middleFlag" width"1100px" height1200px title"文章管理" :visib…...

汇总公安局网站建设想法,QPQ盐浴氮化处理

功能描述 网站管理平台 1、主要功能&#xff1a;网站信息发布功能组件、文章数据转移、内容管理word导入发布、一键排版、统一互动、网站管理、权限分配管理 2、跨浏览器的后台管理界面&#xff0c;支持IE\FIREFOX\CHROME\SAFARI\OPERA及其他第三方浏览器&#xff1b; 3、系统…...

前度开发面试题

面试题总结 vue页面跳转会经过两个钩子函数beforeEach、afterEach 组见守卫 beforeRouteEnter前置组见守卫 *beforeRouteUpdate更新之前 watch和computed区别 数据没有改变&#xff0c;则 computed 不会重新计算&#xff09;。若没改变&#xff0c;计算属性会立即返回之前缓…...

如何保证缓存中都是热点数据?

确保缓存中保留热点数据是关键&#xff0c;因为热点数据通常是最常被访问的数据&#xff0c;提高了缓存的命中率和整体性能。以下是一些策略和方法&#xff0c;能够帮助你维护缓存中的热点数据&#xff1a; 缓存策略&#xff1a; 缓存预热&#xff1a; 在系统启动时或负载较低的…...

什么是Webpack?它的主要功能是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

基于深度学习的人脸性别年龄识别 - 图像识别 opencv 计算机竞赛

文章目录 0 前言1 课题描述2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程 4 具体实现4.1 预训练数据格式4.2 部分实现代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 毕业设计…...

宝塔安装mongodb插件失败的解决办法

安装时始终不成功。 进入控制台进行安装 /www/server/php/71# pecl install mongodb WARNING: channel "pecl.php.net" has updated its protocols, use "pecl channel-update pecl.php.net" to update pecl/mongodb requires PHP (version > 7.2.0, …...

CVE-2018-8174 IE浏览器远程代码执行漏洞

一、漏洞简介 该漏洞影响最新版本的IE浏览器及使用了IE内核的应用程序。用户在浏览网页或打开Office文档时都可能中招&#xff0c;最终被黑客植入后门木马完全控制电脑。微软在4月20日早上确认此漏洞&#xff0c;并于5月8号发布了官方安全补丁&#xff0c;对该0day漏洞进行了修…...

用前端框架Bootstrap和Django实现用户注册页面

01-新建一个名为“mall_backend”的Project 命令如下&#xff1a; CD E:\Python_project\P_001\myshop-test E: django-admin startproject mall_backend02-新建应用并注册应用 执行下面条命令依次创建需要的应用&#xff1a; CD E:\Python_project\P_001\myshop-test\mall…...

MySQL用户管理和授权

用户管理和授权是属于MySQL当中的DCL语句 创建用户以及一些相关操作 明文创建用户 create user zzrlocalhost IDENTIFIED by 123456;create user 这是创建用户的开头zzr表示用户名 localhost&#xff1a;新建的用户可以在哪些主机上登录。即可以使用IP地址&#xff0c;网段&a…...

PCIe 的 MSI 中断详解,寄存器级别的详细流程分析,完全搞懂硬件的工作流程

PCIe 的 MSI 中断 前言 什么是 MSI 中断 (Message Signaled Interrupts) 概念与内容介绍待补充 正文 对 EP 的初始化 需要对 EP 的配置空间 MSI 相关功能的寄存器进行初始化&#xff0c;主要有两个寄存器 Message Address 和 Message Data。它们分别的含义是 EP 产生 MSI …...

软考 系统架构设计师系列知识点之净室软件工程(1)

所属章节&#xff1a; 第5章. 软件工程基础知识 第5节. 净室软件工程 1. 概述 净室&#xff08;Cleaning Room&#xff09;软件工程是一种应用数学与统计学理论&#xff0c;以经济的方式生产高质量软件的工程技术&#xff0c;力图通过严格的工程化的软件过程达到开发中的零缺…...

NFC芯片MS520:非接触式读卡器 IC

MS520 是一款应用于 13.56MHz 非接触式通信中的高集成 度读写卡芯片。它集成了 13.56MHz 下所有类型的被动非接触 式通信方式和协议&#xff0c;支持 ISO14443A 的多层应用。 主要特点 ◼ 高度集成的解调和解码模拟电路 ◼ 采用少量外部器件&#xff0c;即可将输…...

git push 部分 commit

原理&#xff1a;通过rebase修改提交的顺序&#xff0c;然后提交内容 $ git rebase -ivi 编辑器里面按 i 修改你要提交的内容到最上面&#xff0c;然后ESC -> &#xff1a;wq$ git push origin 459ed31a36439c68228ac81c732a4abe3a5de149:master origin 仓库名字&#x…...

idea自动编译以及修改代码后需要执行 mvn clean install 才生效

idea自动编译以及修改代码后需要执行 mvn clean install 才生效 一. idea热部署一、开启IDEA的自动编译&#xff08;静态&#xff09;二、开启IDEA的自动编译&#xff08;动态&#xff09;三、开启IDEA的热部署策略&#xff08;非常重要&#xff09; 二. IDEA 中项目代码修改后…...

21.13 Python 实现端口流量转发

端口流量转发&#xff08;Port Forwarding&#xff09;是一种网络通信技术&#xff0c;用于将特定的网络流量从一个端口或网络地址转发到另一个端口或地址。它在网络中扮演着一个非常重要的角色&#xff0c;在Python语言中实现端口转发非常容易。 如下这段代码实现了一个基本的…...

CNN卷积神经网络模型的GPU显存占用分析

一、参考资料 浅谈深度学习:如何计算模型以及中间变量的显存占用大小 如何在Pytorch中精细化利用显存 二、相关介绍 0. 预备知识 为了方便计算&#xff0c;本文按照以下标准进行单位换算&#xff1a; 1 G 1000 MB1 M 1000 KB1 K 1000 Byte1 B 8 bit 1. 模型参数量的计…...

LSF 概览——了解 LSF 是如何满足您的作业要求,并找到最佳资源来运行该作业的

LSF 概览 了解 LSF 是如何满足您的作业要求&#xff0c;并找到最佳资源来运行该作业的。 IBM Spectrum LSF ("LSF", load sharing facility 的简称) 软件是行业领先的企业级软件。LSF 将工作分散在现有的各种 IT 资源中&#xff0c;以创建共享的&#xff0c;可扩展…...

三.RocketMQ单机安装及集群搭建

RocketMQ单机安装及集群搭建 一&#xff1a;安装环境1.软硬件要求2.下载RocketMQ 二.安装单机MQ1.上传并解压2.目录介绍3.修改MQ启动时初始JVM内存4.启动NameServer与Broker5.测试RocketMQ 三.RocketMQ集群搭建1.集群概念特点2.集群模式分类3.集群工作流程4.双主双从集群搭建4.…...

uniapp 模仿 Android的Menu菜单栏

下面这张图就是我们要模拟的菜单功能 一、模拟的逻辑 1. 我们使用uni-popup组件&#xff08;记得要用hbuilder X导入该组件&#xff09;uni-app官网 2. 将组件内的菜单自定义样式 二、uniapp代码 写法vue3 <template><view><uni-popup ref"showMenu"…...

wordcloud Python中的词云库

Python中的词云库是一个非常流行的文本可视化工具&#xff0c;可以将文本中的关键词以词云形式呈现。本篇文章将详细讲解Python中的词云库的使用和API以及代码注释。 安装词云库 安装词云库的方式很简单&#xff0c;只需要在命令行中使用pip命令即可。具体命令如下所示&#…...

直播间讨论区需要WebSocket,简单了解下

由于 http 存在一个明显的弊端&#xff08;消息只能有客户端推送到服务器端&#xff0c;而服务器端不能主动推送到客户端&#xff09;&#xff0c;导致如果服务器如果有连续的变化&#xff0c;这时只能使用轮询&#xff0c;而轮询效率过低&#xff0c;并不适合。于是 WebSocket…...

2024年天津高职升本科考试将于11月开始报名

2024年天津高职升本科考试文化课网上报名及其现场确认将于11月下旬开始 2023年11月1日&#xff0c;天津招考资讯官方网站发布了本月&#xff08;11月&#xff09;报名事项安排&#xff0c;将进行下列考试项目网上报名工作&#xff0c;2024年备考天津专升本的考生可以看到2024年…...

linux mysql 创建数据库并配置用户远程管理

要在Linux上创建MySQL数据库并配置用户以实现远程管理&#xff0c;您可以执行以下步骤&#xff1a; 1. 登录到MySQL服务器&#xff1a; 在您的Linux终端中&#xff0c;使用以下命令登录到MySQL服务器。您需要提供MySQL服务器的用户名和密码。 mysql -u root -p 输入密码后&a…...