谈一谈你对View的认识和View的工作流程
都2023年了,不会还有人不知道什么是View吧,不会吧,不会吧。按我以往的面试经验来看,View被问到的概率不比Activity低多少哦,个人感觉View在Android中的重要性也和Activity不相上下,所以这篇文章将介绍下View的基础知识及其工作原理。
一、初识View
什么是View ?
所谓的View,就是Android中所有控件的基类(例如:Button、TextView、LinearLayout等等),甚至是ViewGroup也是继承自View的,然而ViewGroup是一个控件组,里面包含许多控件(也就是一组View),所以这就意味着View本身既可以是单个控件,也可以是由许多控件组成的一个控件,这样看来View其实也没那么玄乎啊。
View的位置参数
首先我们要知道,在Android手机中,坐标系是以手机屏幕的最左上角为原点而建立的,大家可以参考下面的图片理解下。
其次,View的初始位置
由四个属性决定,分别是:top、left、right、bottom。其中top和left为View左上角的纵坐标和横坐标,而bottom和right为View右下角的纵坐标和横坐标。(看官注意:这些坐标全都是相对于View所在的父容器来说的,是一个相对坐标,并不是在手机屏幕中的实际坐标)
同样,在下面放上图示帮助大家理解:
所以,通过上面的一通分析,我们可以得出View的宽高和坐标之间的关系:
width = right - left
height = bottom -top
细心的看官可能发现了,在上面我把”初始位置“四个字给标红了。没错,那四个属性不仅仅是初始位置,而且在你的View不论是发生旋转或者平移时候,他们都不会改变,改变的其实是另外的位置参数。从Android3.0开始,View增加了几个额外的参数,它们分别是x、y、translationX、translationY,其中x和y是View左上角的坐标,而translationX、translationY是View左上角相对于父容器的偏移量,(注意:这几个参数同样是针对父容器而言的)
并且translationX和translationY的默认值是0,它们有以下的换算关系:
x = left + translationX
y = top +translationY
所以不难看出,当View发生位置改变时,改变的其实是x、y、translationX、translationY这四个参数。好了,以上就是View位置参数的全部内容,如果以上内容各位看起来比较轻松的话,那么接下来的内容可能比较费劲,接下来继续发车了。
二、DecorView和MeasureSpec
View的三大流程无非就是Measure、Layout、Draw,但这三大流程都是基于DecorView中呈现的,然而想要呈现出View,还需要知道View的大小,在测量过程中MeasureSpec又是其中的关键,所以接下来我们有必要了解下他们。
初识DecorView
DecorView是Activity里的顶级View,它一般来说是一个竖直方向的LinearLayout(这与Android的版本和主题有关),在这个LinearLayout里面有上下两部分,上面是标题栏,下面是内容栏。我们在Activity的onCreate()方法中通过setContentView所设置的布局文件就被加入到了DecorView的内容栏之中,内容栏的id为content,通过ViewGroup content = findViewById(R.android.id.content)
可以得到content,View层的事件都会先经过DecorView之后才继续向下传递的。同样是一图胜千言:
理解MeasureSpec
第一个问题,什么是MeasureSpec?在《Android开发艺术探索》一书中对它的解释是这样的:MeasureSpec翻译过来是”测量规格“或者”测量说明书“,是一个32位的int值,高2位代表SpecMode,低30位代表SpecSize。而SpecMode指测量模式,SpecSize指在某种测量模式下的规格大小
。
第二个问题,MeasureSpec是干啥的?同样书中的解释是:它在很大程度上决定了一个View的尺寸规格,之所以说是很大程度上是因为这个过程还受父容器的影响,因为父容器影响View的MeasureSpec的创建过程。在测量过程中,系统会将View的LayoutParams根据父容器所施加的规则转换成对应的MeasureSpec,然后再根据这个measureSpec来测量出View的宽高。
可谓是听君一席话,胜似听君一席话,我一开始看也是云里雾里的,接下来我尽量不深入代码,带大家通俗的理解一下:
我回答下第一个问题,MeasureSpec其实就是一串数字,一串长度为32位的数字,里面包含着一些View的测量信息。
第二个问题的答案就是,通过这一串数字可以帮助系统测量出View的宽和高。
这够通俗了吧,这就跟你网购的快递一样的,快递单号就是那一串莫名其妙的数字(MeasureSpec),通过这一串数字能帮助你查询到快递运到哪了,换算到View上,不就是帮助系统知道View的宽和高嘛,这是一个道理,听懂就来点掌声。
那么接下来就要详细了解下系统是怎么通过这串数字(MeasureSpec)来测量出View的宽高的。在上面提到SpecMode和SpecSize。 SpecSize比较简单,通俗理解就是View在父容器下的实际大小或者是可用大小
,有人可能会问为什么还会有个可用大小?这里我解释下:当你在布局文件中给定一个View一个确切的大小时,那么SpecSize就是实际大小,例如:android:layout_width = "x dp"
、android:layout_height = "x dp"
。反之如果这两个属性给的值为”match_parent“
、或者是"wrap_content"
时,此时的SpecSize就是父容器下的可用大小。
SpecMode相对于SpecSize而言削微有那么点抽象,它分为三类,分别如下:
- UNSPECIFIE:父容器不对View有任何限制,要多大就给大多,这一般用于系统内部,表示一种测量的状态,一般来说可忽视。
- EXACTLY:父容器已经检测出View所需要的精确大小,这个时候View的最终大小就是SpecSize所指定的值,它对应于
LayoutParams
中的match_parent
和赋予具体数值
的这两种模式- AT_MOST:父容器指定了一个可用大小即SpecSize,View的大小不能大于这个值,具体是什么值需要看不同View的具体实现。它对应于
LayoutParams
中的wrap_content
通俗的说,你在layout布局文件中给View的”match_parent“
、和"wrap_content"
属性设置不同的值,再根据父容器的SpecMode加以对应,就会得到View实际的SpecMode,具体的对应关系如下:图来!!!(图中的parentSize指的是父容器中目前可使用的大小,表格中的UNSPECIFIED中的Size为 0 表示忽略,在普通的View中是不会出现的,只会在例如DecorView这种系统级别的才会出现)
parentSpecMode /childLayoutParams | EXACTLY | AT_MOST | UNSPECIFIED |
---|---|---|---|
dp/px | EXACTLY (childSize) | EXACTLY (childsize) | EXACTLY (childsize) |
match_parent | EXACTLY (parentSize) | AT_MOST (parentSize) | UNSPECIFIED (0) |
wrap_content | AT_MOST (parentSize) | AT_MOST (parentSize) | UNSPECIFIED (0) |
所以,只要提供了父容器的MeasureSpec和子元素的LayoutParams,就可以确定出子View的MeasureSpec了,从而就可以进一步确定出View测量后的大小了,至此MeasureSpec扫盲结束。让我们喝口水,继续讲述View的三大流程。等等,你刚才说,喝什么???
三、View的三大流程
此为面试热点,面试官一般会从这里引入,然后不断对你进行摸底,各位要跳槽的看官要注意了,View的三大流程是指measure、layout、draw,即测量、布局和绘制。其中measure确定View的测量宽高,layout确定View的最终宽高和四个顶点位置,而draw则是将View绘制到屏幕上。所以我们逐一进行分析,同样我也不深入代码,有想深入了解代码的可以自己查阅相关信息或者参考《Android开发艺术探索》一书。
measure过程
measure过程主要分为两类,一类是单个View的measure,另一类是对于ViewGroup的measure。单个View的measure比较简单,直接通过调用自身的measure方法就完成了测量过程。然而对于ViewGroup而言,除了会完成自身的measure过程外,还会去遍历调用所有子元素的measure方法,各个子元素再递归去执行这个流程。
1. View的measure过程
上文有提到View的measure通过调用自身的measure()
方法就完成了测量过程,然而measure()方法中又会去调用onMeasure()
,具体代码如下:
//View的measure方法
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {...// measure ourselves, this should set the measured dimension flag backonMeasure(widthMeasureSpec, heightMeasureSpec);...
}
//View的onMeasure方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec),getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
从上面的代码我们可以知道两点,一是宽和高分别有自己的MeasureSpec,至于什么是MeasureSpec,上文有提到过了。二是宽或高的测量大小是通过getDefaultSize()
方法得到的,至于他是怎么得到的,我们继续往下看:
public static int getDefaultSize(int size, int measureSpec) { int result = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) {case MeasureSpec.UNSPECIFIED: result = size; break;case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = specSize; break; } return result;
}
对于MeasureSpec.getMode()
和MeasureSpec.getSize()
方法我详细解释下,这是系统提供的一个解包方法,也可以理解为解密吧(其实也就是二进制的与操作),将一个measureSpec通过解包,从而得到sepcMode和specSize,再往后就是根据specMode返回对应的大小了。
另外,getDefaultSize()
方法还传入了一个getSuggestedMinimumHeight()
或getSuggestedMinimumWidth()
参数,这看名字应该是一个系统推荐的默认值,至于这个默认值怎么来的,我就不带着大家分析代码了,我直接给出结论,有兴趣的看官可以自行了解,我这里以getSuggestedMinimumWidth()
为例给结论就行,因为getSuggestedMinimumHeight()
也是一模一样的。
getSuggestedMinimumWidth()结论: 如果View没有设置背景,那么返回android:minWidth这个属性所指定的值(这个值可以为0),如果View设置了背景,则返回android:minWidth和背景的最小宽度这两者中的最大值.
面试点细节总结
敲黑板了,注意了,此为魔鬼细节和面试问点,各位看官要注意了
面试官:直接继承自View的自定义控件需要注意什么?
我:当然是需要重写onDraw()方法啦!
面试官:…这简直是一句犀利的废话。
直接继承View的自定义View需要重写onMeasure方法并设置wrap_content时的大小,否则在布局中使用wrap_content时就相当于match_parent,导致使用match_parent和使用wrap_content时完全没有区别。
之所以会出现这样的现象是因为View在布局中使用wrap_content时,那么它的specMode是AT_MOST模式,在这种模式下,它的宽、高specSize都是parentSize
(这一部分前面有讲过,可以查阅表格,如果懒得往上翻的朋友,我会在下面再放一次表格),而parentSize代表的是父容器中目前可以使用的大小。所以在这种情况下,View的宽高就会等于父容器可使用空间大小,我们可以再看表格,艾,巧了,当我们使用match_parent时,specSize同样也是parentSize,所以呈现的效果完全一致,这下大家都明白了吧?
parentSpecMode /childLayoutParams | EXACTLY | AT_MOST | UNSPECIFIED |
---|---|---|---|
dp/px | EXACTLY (childSize) | EXACTLY (childsize) | EXACTLY (childsize) |
match_parent | EXACTLY (parentSize) | AT_MOST (parentSize) | UNSPECIFIED (0) |
wrap_content | AT_MOST (parentSize) | AT_MOST (parentSize) | UNSPECIFIED (0) |
呐,还是给大家举个栗子,帮助理解。
大家可以看到我在布局中加了两个控件,一个是普通的View,背景色为黑色(这里我们也可以看成自定义View),另一个是TextView,背景色为白色。这控件的宽高属性全部是wrap_content
,然而我们自定义的View却撑满了整个屏幕,TextView却没有。这是因为TextView中已经重写了onMeasure()方法,在方法中对specMode为AT_MOST时,做了特殊处理,大家感兴趣可以自己查看源码,而View中没有处理。所以出现了上述的问题。
所以当大家在写自定义View时,记得也加入这样的处理,我在下面为大家放上一个解决方案,具体值得大小还需要你们自己去灵活定义:
//代码来源于《Android开发艺术探索》
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) { setMeasuredDimension(mWidth, mHeight); } else if (widthMode == MeasureSpec.AT_MOST) { setMeasuredDimension(mWidth, heightSize); } else if (heightMode == MeasureSpec.AT_MOST) { setMeasuredDimension(widthSize, mHeight); }
}
2. ViewGroup的measure过程
ViewGroup自身是没有重写onMeasure()方法的,而View是有重写的。但是ViewGroup提供了一个measureChild
方法,其作用就是取出子元素的LayoutParams,进一步获得子元素的MeasureSpec,接着将MeasureSpec传递给View的measure方法进行测量,View的measure测量流程已经在上面做了详细分析了。
大家看到这应该也明白了,为什么自定义View不用必须重写onMeasure,而自定义ViewGroup必须重写onMeasure方法的原因了
所以ViewGroup的测量流程简单而言可以分为两块内容,
第一块递归对子View进行measure
,第二块根据每个子View的测量结果,累计加总测量出ViewGroup自身的宽高
。第一块内容在上文详细介绍过,因此我们主要关注第二块内容,接下来以LinearLayout为例子进行介绍,我们先来看下LinearLayout的onMeasure方法:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {if (mOrientation == VERTICAL) {measureVertical(widthMeasureSpec, heightMeasureSpec);} else {measureHorizontal(widthMeasureSpec, heightMeasureSpec);}
}
上述代码可谓简单明了,我们就只以VERTICAL方向上去看一下,另一个也大同小异,大家可以自行了解,由于measureVertical方法比较长,我就截取部分源码,描述下大概逻辑,首先看代码:
void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {mTotalLength = 0;...// See how tall everyone is. Also remember max width.//(遍历每个子View的高度,并且记录下总高度,其中mTotalLength就是总高度)for (int i = 0; i < count; ++i) {final View child = getVirtualChildAt(i);...// Determine how big this child would like to be. If this or// previous children have given a weight, then we allow it to// use all available space (and we will shrink things later// if needed).final int usedHeight = totalWeight == 0 ? mTotalLength : 0;measureChildBeforeLayout(child, i, widthMeasureSpec, 0,heightMeasureSpec, usedHeight);final int childHeight = child.getMeasuredHeight();final int totalLength = mTotalLength;mTotalLength = Math.max(totalLength, totalLength + childHeight + lp.topMargin +lp.bottomMargin + getNextLocationOffset(child));...}//所有子元素遍历结束,开始测量自身大小// Add in our padding,加顶部和底部的padding统计进总高度mTotalLength += mPaddingTop + mPaddingBottom;int heightSize = mTotalLength;// Check against our minimum heightheightSize = Math.max(heightSize, getSuggestedMinimumHeight());// Reconcile our calculated size with the heightMeasureSpec// 根据父容器的大小和自身的MeasureSpec计算出最终高度,因为子元素高度总和是不能超过父元素剩余空间的int heightSizeAndState = resolveSizeAndState(heightSize, heightMeasureSpec, 0);...maxWidth += mPaddingLeft + mPaddingRight;// Check against our minimum widthmaxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());//传入最终测量出的宽高尺寸,从而设置ViewGroup的宽高setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),heightSizeAndState);
}
上述代码的主要逻辑就是系统会遍历所有子元素并对他们执行measureChildBeforeLayout
方法,在这个方法内部会调用子元素的measure方法,也就是进入到了第一块内容中(上文已经讲解过),系统还通过mTotalLength来记录LinearLayout在竖直方向的总高度,每测量出一个子元素,mTotalLength就会增加,增加的部分主要包括子元素的高度以及子元素在竖直方向上的margin、padding等。最终设置ViewGroup的测量宽高,至此测量完成!
面试点细节总结
- 自定义ViewGroup,继承ViewGroup后,必须要重写onMeasure方法测量自身和子View,进而重写onLayout,这点与自定义View差别较大,需要特别注意.
- 不论是自定义View还是自定义ViewGroup,他们在measure过程得到的宽高都不是最终宽高,仅仅是测量宽高。最终宽高是在onLayout过程中才真正确定的,所以要获取一个控件的宽高,最好在onLayout方法中去获取。当然大多数情况下,控件的测量宽高和最终宽高是相等的.
- 由于View的measure过程和Activity的生命周期方法是不同步执行的,因此无法保证Activity执行了onCreate、onStart、onResume时某个View已经被测量完毕了,如果此时View还没有测量完毕,我们获取到的宽高值将会是0,要解决这种问题,我们可以采用
view.post(runnable)
方法,通过post将一个runnable投递到消息队列尾部,等View初始化完成后,就会从Looper中调用此runnable,从而拿到测量出的宽高值,代码示例如下:
mView.post(new Runnable() {@Overridepublic void run() {int width = mView.getMeasuredWidth();int height = mView.getMeasuredHeight();}});
layout过程
Layout流程是用于确定View或ViewGroup的位置,因为layout流程相对于measure而言比较简单,我们先看看view的layout大致代码逻辑:
public void layout(int l, int t, int r, int b) {...int oldL = mLeft;int oldT = mTop;int oldB = mBottom;int oldR = mRight;boolean changed = isLayoutModeOptical(mParent) ?setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {onLayout(changed, l, t, r, b);...}...
}
在上述代码中,大致流程是,layout
方法首先会通过setFrame方法来设定View的四个顶点位置,即初始化mLeft、mTop、mRight、mBottom这四个值,View的四个顶点一旦确定,View在父容器中的位置也就随之确定了。接下来就会调用onLayout
方法,这个方法的用途是父容器确定子元素位置的,通俗而言就是layout是确定自身的位置,onLayout是确定其子View的位置
,因为单个View没有子元素,ViewGroup类布局的不确定性,所以他们均对onLayout
方法都是空实现,即如下所示:
/*** Called from layout when this view should* assign a size and position to each of its children.** Derived classes with children should override* this method and call layout on each of* their children.*/
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
}
因为LinearLayout继承自ViewGroup,所以它必然实现了onLayout方法,所以我们继续以它为例,看看它是如何实现的,代码如下所示:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {if (mOrientation == VERTICAL) {layoutVertical(l, t, r, b);} else {layoutHorizontal(l, t, r, b);}
}
啊哈,看来和onMeasure()
中的实现逻辑类似,我们还是以layoutVertical
进行讲解,同样继续给出主要代码逻辑:
void layoutVertical(int left, int top, int right, int bottom) {...final int count = getVirtualChildCount();...for (int i = 0; i < count; i++) {final View child = getVirtualChildAt(i);if (child == null) {childTop += measureNullChild(i);} else if (child.getVisibility() != GONE) {final int childWidth = child.getMeasuredWidth();final int childHeight = child.getMeasuredHeight();final LinearLayout.LayoutParams lp =(LinearLayout.LayoutParams) child.getLayoutParams();...if (hasDividerBeforeChildAt(i)) {childTop += mDividerHeight;}childTop += lp.topMargin;setChildFrame(child, childLeft, childTop + getLocationOffset(child),childWidth, childHeight);childTop += childHeight + lp.bottomMargin + getNextLocationOffset(child);i += getChildrenSkipCount(child, i);}}
}
所以综上所述:
layoutVertical
方法会遍历所有子元素并调用setChildFrame
方法来为子元素指定对应位置,其中childTop记录当前末端子元素的高度位置,childTop会逐渐增大,意味着后面的子元素会被放置在靠下的位置,这正是竖直方向上LinearLayout的特性。
再简单说一下
setChildFrame
方法,它仅仅是调用子元素(这里我们可以看成是儿子元素
)的layout方法,然后当该元素(儿子元素)确定了自己的位置以后又调用onLayout方法安排其子元素(孙子元素
)的位置。好家伙,这简直就是俄罗斯套娃(递归)。
draw过程
Draw过程就更简单了,尤其是对于做了许多自定义View的友友来说。它的作用就是将View绘制到屏幕上面,绘制过程大致如下:
- 绘制背景background.draw(canvas).
- 绘制自己 (onDraw).
- 绘制children (dispatchDraw).
- 绘制装饰 (onDrawScrollBars).
关于绘制过程,是三大流程中最为简单的了,看官可以自行查看源码,这里就不再赘述了,另外ViewGroup一般不用重写onDraw来绘制自己,只需要对子View进行绘制就可以。但明确知道一个ViewGroup需要通过onDraw来绘制内容时,我们需要调用setViewNotDraw(false)
来进行设置;
好了,至此View三大工作流程已经讲解完毕,没错,接下来当然是划重点啦。
四、自定义View相关总结
自定义View的分类
- 继承View:需重写onDraw方法,一般用于实现一些不规则的效果。
- 继承ViewGroup:需重写onMeasure、onLayout方法,即自己定义一种除了像linearLayout、RelativeLayout等,这几种系统布局之外的布局,这种情况比较少
- 继承特定的View:比如继承ImgView等,一般用于拓展某种已有的View的功能。
- 继承特定的ViewGroup: 比如继承LinearLayout,一般也是用于拓展功能。但好处是它不需要自己重写onMeasure和onLayout方法,并且也比较常用。
自定义View的注意事项
- 让View支持wrap_content,这一点在上面
View的measure过程的面试点细节总结
里详细介绍过。 - 在自定义View时,不要在
onDraw()
方法中定义变量和执行循环操作,不然会导致内存溢出和卡顿掉帧的现象。 - 如果View中有线程或者动画,需要及时停止,否则会造成内存泄露的情况。
- View带有滑动嵌套情形时,需要处理好滑动冲突。
- 不建议使用自定义的Handler,而应该使用
view.post(runnable)
方法进行替代。 - 如果有必要,让你的View支持padding。对于直接继承View的控件,如果不在
onDraw()
方法中处理padding,那么padding属性是没有效果的。对于直接继承自ViewGroup的控件,需要在onMeasure()
和onLayout()
中考虑padding和子元素的margin对其造成的影响,否则也会导致padding和子元素的margin失效。
更多Android 面试知识点:https://qr18.cn/CKV8OZ
相关文章:

谈一谈你对View的认识和View的工作流程
都2023年了,不会还有人不知道什么是View吧,不会吧,不会吧。按我以往的面试经验来看,View被问到的概率不比Activity低多少哦,个人感觉View在Android中的重要性也和Activity不相上下,所以这篇文章将介绍下Vie…...

Redis集群的脑裂问题
集群脑裂导致数据丢失怎么办? 什么是脑裂? 先来理解集群的脑裂现象,这就好比一个人有两个大脑,那么到底受谁控制呢? 那么在 Redis 中,集群脑裂产生数据丢失的现象是怎样的呢? 在 Redis 主从架…...

互斥信号+任务临界创建+任务锁
普通信号量 1、信号量概念 2、创建信号量函数 3、互斥信号量 创建互斥信号量函数 等待信号量函数 释放互斥信号量 4、创建任务临界区 5、任务锁 任务上锁函数 编辑 任务结束函数 效果 普通信号量 1、信号量概念 信号量像是一种上锁机制,代码必须获…...

Elasticsearch7.8.0版本进阶——文档搜索
目录一、文档搜索的概述二、倒排索引不可变的优点三、倒排索引不可变的优点一、文档搜索的概述 早期的全文检索会为整个文档集合建立一个很大的倒排索引并将其写入到磁盘。 一旦新的索引就绪,旧的就会被其替换,这样最近的变化便可以被检索到。倒排索引被…...

spring security权限问题
org.springframework.boot spring-boot-starter-security 引入jar extends WebSecurityConfigurerAdapter 用来配置登陆和权限 configure(HttpSecurity http) 覆盖这个方法 //配置授权相关的 .authorizeRequests () //任何请求 .anyRequest() //要求授权后可以访问 .authen…...

mysql 8.0.22安装
mysql8.0.22安装1. 配置my.ini2. 添加环境变量3. 安装mysql3.1 mysql初始化3.2 安装mysql服务3.3 启动mysql服务4. 连接数据库修改连接数据库的密码前提:已经从官网下载mysql8.0.22安装包并解压(下载地址:https://dev.mysql.com/downloads/in…...

Mysql系列:Mysql5.7编译安装
系统环境:Centos7 1:下载mysql源码包 https://dev.mysql.com/downloads/mysql/5.7.html downloads 选择MySQL Community Server>source_code>Generic Linux (Architecture Independent), Compressed TAR Archive -> 选择需要的mysql版本&…...

设备树(配合LED驱动说明)
目录 一、起源 二、基本组成 三、基本语法 四、特殊节点 4.1 根节点 4.2 /memory 4.3 /chosen 4.4 /cpus 多核CPU支持 五、常用属性 5.1 phandle 5.2 地址 --------------- 重要 5.3 compatible --------------- 重要 5.4 中断 --------------- 重要 5.5 …...

(二十六)大白话如何从底层原理解决生产的Too many connections故障?
今天我们继续讲解昨天的那个案例背景,其实就是经典的Too many connections故障,他的核心就是linux的文件句柄限制,导致了MySQL的最大连接数被限制,那么今天来讲讲怎么解决这个问题。 其实核心就是一行命令: ulimit -H…...

ASEMI高压MOS管60R380参数,60R380特征,60R380应用
编辑-Z ASEMI高压MOS管60R380参数: 型号:60R380 漏极-源极电压(VDS):600V 栅源电压(VGS):20V 漏极电流(ID):11A 功耗(PD&#x…...

Python期末试卷
《Python程序设计基础》期末试题 班级 学号 姓名 一.选择题(须知:答案写到下方的表格中,其它一律无效.每题2分,共40分) 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 1.在Python交互…...

Linux | 网络通信 | http协议介绍 | cookie策略讲解
文章目录url统一资源定位符http协议介绍GET vs POSThttp状态码http常见headercookie session上篇博客定制了一个协议,该协议用来进行简单的计算,其包含了数据的序列化和反序列化,编码和解码的定制,并且该协议基于TCP通信…...

招投标系统简介 招投标系统源码 java招投标系统 招投标系统功能设计
项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及…...

winapi获取和修改camera raw界面元素数据
camera raw 界面如下: 需求就是根据 windows api 来操作界面右边的色温、色调、曝光等属性,进而对图片进行调色。根据 spy 捕获的窗口信息,理论上是可以拿到并修改值的。 根据 class 可以先拿到窗口句柄: #define CAMERA_RAW_CLA…...

C++问答汇总_2023自用
C是一种通用编程语言,具有高级抽象、强类型和编译性能等特点。C语言具有许多特性,包括面向对象编程、模板、多态、运算符重载等等。它广泛应用于各种领域,如系统软件、嵌入式系统、游戏开发、科学计算等等。 1、C11相对于C98的新特性…...

IDA 实战--(2)熟悉工具
布局介绍 软件启动后会 有几个选项,一般直接选择Go 即可 之后的工作台布局如下 开始分析 分析的第一个,将PE 文件拖入工作区 刚开始接触,我们先保持默认选项,其它选项后面会详细讲解,点击OK 后,等待分析…...

Deep Unsupervised Learning using Nonequilibrium Thermodynamics论文翻译学习
Deep Unsupervised Learning using Nonequilibrium Thermodynamics Author: Jascha Sohl-Dickstein Link: http://proceedings.mlr.press/v37/sohl-dickstein15.pdf Score: ⭐️⭐️⭐️⭐️⭐️ Status: Done Type: Academic Journal 备注: 首篇扩散模型论文 A central prob…...

使用Autoware标定工具包联合标定相机和激光雷达
前面文章介绍了,安装autoware标定工具包、ros驱动usb相机、robosense-16线激光雷达的使用,本文记录使用Autoware标定工具包联合标定相机和激光雷达的过程。1.ros驱动相机,启动相机;启动激光雷达2.联合录制bag包rosbag record -a 参…...

了解线程安全
线程安全是多线程的重点和难点。 线程安全概念 线程安全:在多线程的各种随机调度顺序下,代码没有bug,都能够符合预期的方式来执行,此时认为线程安全 线程不安全:如果在多线程随机调度下代码出现bug,此时…...

【git】git版本控制
目录 1.在合适的位置打开bush,创建仓库 2.检查:跳转到当前文件夹,显示当前文件夹的相对路径 3.初始化 4.创建一个文本文件readme.txt 5.手动向readme文件中添加一些内容 6.把文件添加到暂存区 7.把文件提交到git仓库 8.手动修改readme.txt文件 9.查看当前…...

模电学习7. 三极管特性曲线与静态工作点
模电学习7. 三极管特性曲线与静态工作点一、三极管的伏安特性曲线1. 三极管的伏安特性曲线2. 三极管的静态工作点二、合适的静态工作点选择1. 合适静态工作点条件2. 静态工作点的确定三、使用立创EDA仿真查看静态工作点1. 搭建如下图所示测试电路2. 点击菜单仿真、仿真设置3. 运…...

LeetCode题解:633. 平方数之和,双指针,JavaScript,详细注释
原题链接: https://leetcode.cn/problems/sum-of-square-numbers/ 解题思路: a和b一定是000到c\sqrt cc之间的某个值。将a的初始值设为0。b的初始值设为c\sqrt cc,b必须为整数。a和b向中间逼近,查找满足条件的值。由于a和b是…...

Keil编译头文件iec_std_functions.h错误解决
Keil 编译IEC61131-3库,头文件,大量出现以下错误; cast to type ? is not allowed compiling resource1.c... ..\PLC\rts\matiec\lib\C\iec_std_functions.h(192): error: #119: cast to type "TIME" is not allowed…...

2022 赣育杯 CTF --- Crypto Lost_N wp
文章目录前言题目解题过程解题代码前言 这是去年江西省赛一道有点小坑的密码题,当时没做出来,今天回想起来重新做一下并且记录一下。 题目 Lost_N.py import gmpy2 from Crypto.Util.number import * # part1 flag bSangFor{} d getPrime(435) cou…...

【趋势分析方法三】MATLAB代码实现TFPW-MK检验
目前水文时间序列趋势分析的方法很多,主要分为参数检验和非参数检验两大类: 参数检验中常用的有线性回归法、滑动平均法、累积距平法等非参数检验则主要包括Mann-Kendal(MK)法和 Spearman 秩次相关法等 虽然从理论上讲ÿ…...

一文学会 Spring 整合 MyBatis
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

ElasticSearch - 文档 | 索引文档 | 检索文档 | 创建索引并指明映射
文章目录1. ElasticSearch是面向文档的2. 索引员工文档3. 检索员工文档4. 映射1. ElasticSearch是面向文档的 在应用程序中对象很少只是一个简单的键和值的列表。通常,它们拥有更复杂的数据结构,可能包括日期、地理信息、其他对象或者数组等。 Elastic…...

SQL中的DML、DDL、DCL分别是什么意思
SQL命令的分类 数据定义语言 DDL(DataDefinition Language) 是 SQL 语言集中负责数据结构定义。 DDL 的核心指令是CREATE、ALTER、DROP。 操作的对象包括:库、表、视图、索引等。 如:CREATE TABLE ; ALTER INDEX; DROP VIEW; 数据…...

kubeasz部署k8s高可用集群
前言:如无特殊说明,所有操作都用root账号在所有节点执行。 说明:kubeasz是一款国产开源的k8s部署软件,采用ansible role的部署方式,部署k8s二进制集群。熟悉ansible role的用该软件部署k8s方便快捷。 一、机器 deplo…...

2022年工程机械出口专题研究【重工】
文章目录2022年工程机械出口专题研究1、中国是全球工程机械第一大市场,竞争力逐步提升2、工程机械出口高增,市场分布趋于多元,企业营收获益3、海外市场高速增长原因为何?4、海外市场增长动能预测附件:2022年工程机械出…...