Android自定控件感觉无从下手看这里

文章目录

    • 三个方法
    • 标准自定义控件的要求
    • 一、自定义View
    • 二、测量:onMeasure
      • 2.1、测量并得到高度和宽度后的运行效果
      • 2.2、此外我们还要加上pading的距离,否则我们在xml中设置的padding就不会生效
      • 2.3、 至此一个简单的自定义View已经完成,自定义View的核心就是测量方法 onMeasure
    • 三、自定义ViewGroup
      • 3.1、 跟自定义View不同,onMeasure测量时首先根据子View个数区分两种情况:
      • 3.2、计算没有子View时的宽度和高度
      • 3.3、计算有子View时的高度和宽度
      • 3.4、计算宽度
      • 3.5、计算高度
      • 3.6、根据父控件中设置的宽度和高度(即xml中设置的)计算自身宽度和高度
      • 3.7、onLayout 用来布局各个子控件的位置
      • 3.8、最后来个效果图
    • 四、到此为止最基本的自定义知识就完了
    • 五、最后就要考虑性能问题

三个方法

onMesure:用来计算控件的宽和高,我们在xml中给控件设置的宽高就是通过这个来计算的。

onLayout:这个方法是用来摆放子控件的,所以自定义View中没有,自定义ViewGroup中才有。

onDraw:一般情况下自定View才有绘制,自定义ViewGroup默认不会调用此方法,因为ViewGroup的作用就是布局子控件,没什么可绘制的。

标准自定义控件的要求

1、xml可配置属性
2、代码动态设置属性

一、自定义View

public class LearnView extends View {private String text;private Paint mPaint;private Rect mTextBound;public LearnView(Context context) {this(context, null);}public LearnView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public LearnView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LearnView);text = ta.getString(R.styleable.LearnView_learn_text);ta.recycle();mPaint = new Paint();mPaint.setTextSize(50);mTextBound = new Rect(); //根据文字内容获取一个矩形mPaint.getTextBounds(text, 0, text.length(), mTextBound);}@Overrideprotected void onDraw(@NonNull Canvas canvas) {super.onDraw(canvas);canvas.drawText(text, 0, mTextBound.height(), mPaint);}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><com.yl.pictureeditordemo.ui.view.LearnViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:learn_text="测试" /></LinearLayout>

可以看到虽然设置的宽高都是“wrap_content”,却并没有起作用,这时候就需要 onMeasure 方法了

在这里插入图片描述

二、测量:onMeasure

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int specMode = MeasureSpec.getMode(widthMeasureSpec);int specWidth = MeasureSpec.getSize(widthMeasureSpec);if (specMode == MeasureSpec.EXACTLY) {}else if (specMode==MeasureSpec.AT_MOST){}}
  1. 首先这里有两个参数:widthMeasureSpec、heightMeasureSpec,他们都是由父控件中传过来的值;
  2. 每一个参数中都封装了两个值,一个mode,一个size,说直白点就是将两个 int 值组合成为了一个 int 值,具体怎么封装的不用太关心;
  3. 这里的mode又对应了三个常量:MeasureSpec.UNSPECIFIED、MeasureSpec.EXACTLY、MeasureSpec.AT_MOST,我们以宽度为例来说明;
  • MeasureSpec.UNSPECIFIED:不用关心,一般是系统级别才会使用;
  • MeasureSpec.EXACTLY:代表设置了固定值,比如设置了100dp,如果是match_parent也算固定值,因为它代表充满父控件,就是父控件的宽度;
  • MeasureSpec.AT_MOST:代表设置了wrap_content,此时宽度不固定,就需要通过实际情况计算来得到;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><!--宽度为MeasureSpec.AT_MOST模式--><com.yl.pictureeditordemo.ui.view.LearnViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/teal_200"app:learn_text="测试" /><!--宽度为MeasureSpec.EXACTLY模式--><com.yl.pictureeditordemo.ui.view.LearnViewandroid:layout_width="100dp"android:layout_height="wrap_content"android:background="@color/teal_200"app:learn_text="测试" /><!--宽度为MeasureSpec.EXACTLY模式--><com.yl.pictureeditordemo.ui.view.LearnViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/teal_200"app:learn_text="测试" /></LinearLayout>

2.1、测量并得到高度和宽度后的运行效果

可以看到此时我们设置的 wrap_content 有效果了

在这里插入图片描述

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);//计算宽度int specWidthMode = MeasureSpec.getMode(widthMeasureSpec);int specWidth = MeasureSpec.getSize(widthMeasureSpec);if (specWidthMode == MeasureSpec.EXACTLY) {//固定宽度模式下直接赋值得到宽度width = specWidth;} else if (specWidthMode == MeasureSpec.AT_MOST) {//wrap_content模式下通过计算得到宽度width = mTextBound.width();}//计算高度int specHeightMode = MeasureSpec.getMode(heightMeasureSpec);int specHeight = MeasureSpec.getSize(heightMeasureSpec);if (specHeightMode == MeasureSpec.EXACTLY) {height = specHeight;} else if (specWidthMode == MeasureSpec.AT_MOST) {height = mTextBound.height();}//计算完成后使用setMeasuredDimension(width, height);}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><!--宽度为MeasureSpec.AT_MOST模式--><com.yl.pictureeditordemo.ui.view.LearnViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/teal_200"app:learn_text="测试" /><!--宽度为MeasureSpec.EXACTLY模式-->
<!--    <com.yl.pictureeditordemo.ui.view.LearnView-->
<!--        android:layout_width="100dp"-->
<!--        android:layout_height="wrap_content"-->
<!--        android:background="@color/teal_200"-->
<!--        app:learn_text="测试" />--><!--宽度为MeasureSpec.EXACTLY模式-->
<!--    <com.yl.pictureeditordemo.ui.view.LearnView--><!--        android:layout_width="match_parent"--><!--        android:layout_height="wrap_content"--><!--        android:background="@color/teal_200"--><!--        app:learn_text="测试" />--></LinearLayout>

2.2、此外我们还要加上pading的距离,否则我们在xml中设置的padding就不会生效

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);//1、计算宽度int specWidthMode = MeasureSpec.getMode(widthMeasureSpec);int specWidth = MeasureSpec.getSize(widthMeasureSpec);if (specWidthMode == MeasureSpec.EXACTLY) {//固定宽度模式下直接赋值得到宽度width = specWidth;} else if (specWidthMode == MeasureSpec.AT_MOST) {//wrap_content模式下通过计算得到宽度width = mTextBound.width() + getPaddingLeft() + getPaddingRight();}//2、计算高度int specHeightMode = MeasureSpec.getMode(heightMeasureSpec);int specHeight = MeasureSpec.getSize(heightMeasureSpec);if (specHeightMode == MeasureSpec.EXACTLY) {height = specHeight;} else if (specWidthMode == MeasureSpec.AT_MOST) {height = mTextBound.height() + getPaddingTop() + getPaddingBottom();}//3、计算完成后使用setMeasuredDimension(width, height);}

要注意测量结果加上padding过后我们实际绘制时的位置也要改变

    @Overrideprotected void onDraw(@NonNull Canvas canvas) {super.onDraw(canvas);canvas.drawText(text, getPaddingLeft(), mTextBound.height() + getPaddingTop(), mPaint);}

2.3、 至此一个简单的自定义View已经完成,自定义View的核心就是测量方法 onMeasure

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><!--宽度为MeasureSpec.AT_MOST模式--><com.yl.pictureeditordemo.ui.view.LearnViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/teal_200"android:padding="20dp"app:learn_text="测试" /><!--宽度为MeasureSpec.EXACTLY模式--><!--    <com.yl.pictureeditordemo.ui.view.LearnView--><!--        android:layout_width="100dp"--><!--        android:layout_height="wrap_content"--><!--        android:background="@color/teal_200"--><!--        app:learn_text="测试" />--><!--宽度为MeasureSpec.EXACTLY模式--><!--    <com.yl.pictureeditordemo.ui.view.LearnView--><!--        android:layout_width="match_parent"--><!--        android:layout_height="wrap_content"--><!--        android:background="@color/teal_200"--><!--        app:learn_text="测试" />--></LinearLayout>

三、自定义ViewGroup

相对于自定义View来说,自定义ViewGroup不仅要考虑自身的高度和宽度,还要考虑各个子控件的高度和宽度,以及在自定义控件中的摆放位置。

public class LearnViewGroup extends ViewGroup {public LearnViewGroup(Context context) {this(context, null);}public LearnViewGroup(Context context, AttributeSet attrs) {this(context, attrs, 0);}public LearnViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {}
}

3.1、 跟自定义View不同,onMeasure测量时首先根据子View个数区分两种情况:

  • 有子View
  • 没有子View
    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int childCount = getChildCount();if (childCount == 0) {//没有子View} else {//有子View}}

3.2、计算没有子View时的宽度和高度

没有子View时跟自定义View一样的方法获取高度和宽度

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int childCount = getChildCount();if (childCount == 0) { //没有子ViewmWidth = measureWidthAndHeight(widthMeasureSpec);mHeight = measureWidthAndHeight(heightMeasureSpec);setMeasuredDimension(mWidth, mHeight);} else {  //有子View}}
    private int measureWidthAndHeight(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.EXACTLY) {//固定值模式,直接获取父控件传入的值result = specSize;} else if (specMode == MeasureSpec.AT_MOST) {//自定义ViewGroup在设置为wrap_content,并且没有子控件时高度/宽度直接设置为0result = 0;}return result;}

3.3、计算有子View时的高度和宽度

注意计算高度和宽度的方法不一样, 比如下面一个ViewGroup中有三个子View,我们这里的例子只考虑竖向排列

在这里插入图片描述

3.4、计算宽度

循环获取每个子控件的宽度并加上其左右的margin值,然后循环获取最大的子控件的宽度;
最后加上本身的leftPadding 和 rightPadding,就得到了我们最终需要得到的宽度;

左边红色的线代表 leftMargin,是一定有的,右边黄色的代表 rightMargin,至少存在一条,否则右边框就会紧贴最右边的第二个子控件,所以要这样算。

在这里插入图片描述

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int childCount = getChildCount();if (childCount == 0) { //没有子ViewmWidth = measureWidthAndHeight(widthMeasureSpec);mHeight = measureWidthAndHeight(heightMeasureSpec);setMeasuredDimension(mWidth, mHeight);} else {  //有子Viewint childViewsWidth = 0;for (int i = 0; i < childCount; i++) {View childView = getChildAt(i);//将widthMeasureSpec和heightMeasureSpec传入子控件,提供给子控件测量依据measureChild(childView, widthMeasureSpec, heightMeasureSpec);MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();//获取每个子控件的宽度并得到最大的那个值childViewsWidth = Math.max(childViewsWidth, childView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);}//计算最终的宽度和高度,不要忘记加上本身的mWidth = childViewsWidth + getPaddingLeft() + getPaddingRight();}}

注意这里有句代码:MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();
我们需要重写 generateLayoutParams 方法,不然会报类型转换错误。

    @Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {return new MarginLayoutParams(getContext(),attrs);}

3.5、计算高度

把所有子控件的高度累加,并算出每个子控件的 topMargin 和 BottomMarin,也累加起来;
最后加上本身的 topPadding 和 bottomPadding,就得到了我们最终需要得到的高度;
在这里插入图片描述

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int childCount = getChildCount();if (childCount == 0) { //没有子ViewmWidth = measureWidthAndHeight(widthMeasureSpec);mHeight = measureWidthAndHeight(heightMeasureSpec);setMeasuredDimension(mWidth, mHeight);} else {  //有子Viewint childViewsWidth = 0;int childViewsHeight = 0;int childViewsMarginTop = 0;int childViewsMarginBottom = 0;for (int i = 0; i < childCount; i++) {View childView = getChildAt(i);//将widthMeasureSpec和heightMeasureSpec传入子控件,提供给子控件测量依据measureChild(childView, widthMeasureSpec, heightMeasureSpec);MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();//获取每个子控件的宽度并得到最大的那个值childViewsWidth = Math.max(childViewsWidth, childView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);//获取每个子控件的高度并累加childViewsHeight += childView.getMeasuredHeight();//累加margin值childViewsMarginTop += lp.topMargin;childViewsMarginBottom += lp.bottomMargin;}//计算最终的宽度和高度,不要忘记加上本身的mWidth = childViewsWidth + getPaddingLeft() + getPaddingRight();mHeight = childViewsHeight + childViewsMarginTop + childViewsMarginBottom + getPaddingTop() + getPaddingBottom();//使用setMeasuredDimension(mWidth, mHeight);}}

3.6、根据父控件中设置的宽度和高度(即xml中设置的)计算自身宽度和高度

上面的代码在有子控件时,最终使用的代码还未考虑到固定值还是 wrap_content,这样的情况在xml中设置的值是无效的;
所以根据子控件计算出了宽度和高度之后还要根据mode来决定最终的宽度和高度,也就是这里的方法 measureWidthAndHeight(int measureSpec,int size)的用处。

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int childCount = getChildCount();if (childCount == 0) { //没有子ViewmWidth = measureWidthAndHeight(widthMeasureSpec);mHeight = measureWidthAndHeight(heightMeasureSpec);setMeasuredDimension(mWidth, mHeight);} else {  //有子Viewint childViewsWidth = 0;int childViewsHeight = 0;int childViewsMarginTop = 0;int childViewsMarginBottom = 0;for (int i = 0; i < childCount; i++) {View childView = getChildAt(i);measureChild(childView, widthMeasureSpec, heightMeasureSpec);MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();//获取每个子控件的宽度并得到最大的那个值childViewsWidth = Math.max(childViewsWidth, childView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);//获取每个子控件的高度并累加childViewsHeight += childView.getMeasuredHeight();//累加margin值childViewsMarginTop += lp.topMargin;childViewsMarginBottom += lp.bottomMargin;}//计算最终的宽度和高度,不要忘记加上本身的mWidth = childViewsWidth + getPaddingLeft() + getPaddingRight();mHeight = childViewsHeight + childViewsMarginTop + childViewsMarginBottom + getPaddingTop() + getPaddingBottom();//使用setMeasuredDimension(measureWidthAndHeight(widthMeasureSpec, mWidth), measureWidthAndHeight(heightMeasureSpec, mHeight));}}
    private int measureWidthAndHeight(int measureSpec,int size) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.EXACTLY) {//固定值模式,直接获取父控件传入的值result = specSize;} else if (specMode == MeasureSpec.AT_MOST) {//自定义ViewGroup在设置为wrap_content,宽度/高度就是根据子view和自身的padding计算出来的值result = size;}return result;}

3.7、onLayout 用来布局各个子控件的位置

因为我们是垂直排列,所以这里每个子控件的左边位置、右边位置、下边位置都比较好理解。
左边位置:leftPadding + 子控件的leftMargin
右边位置:左边位置 + 子控件自身的宽度
下边位置:上边位置 + 子控件自身的高度
这里的上边位置需要计算每个子控件的高度及其topMargin、bottomMargin,然后用一个变量 countTop 用来记录累加的和。
countTop = 子控件高度(下边位置-上边位置)+ 子控件的topMargin + 子控件的bottomMargin
上边位置:countTop + 子控件自身高度

    @Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int left, top, right, bottom;int childCount = getChildCount();int countTop = getPaddingTop();for (int i = 0; i < childCount; i++) {View view = getChildAt(i);MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();left = getPaddingLeft() + layoutParams.leftMargin;top = countTop + layoutParams.topMargin;right = left + view.getMeasuredWidth();bottom = top + view.getMeasuredHeight();view.layout(left, top, right, bottom);countTop += (bottom - top) + layoutParams.topMargin + layoutParams.bottomMargin;}}

在这里插入图片描述

3.8、最后来个效果图

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><com.yl.pictureeditordemo.ui.view.LearnViewGroupandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/purple_200"android:padding="20dp"><com.yl.pictureeditordemo.ui.view.LearnViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/teal_200"android:padding="15dp"app:learn_text="测试" /><com.yl.pictureeditordemo.ui.view.LearnViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="20dp"android:background="@color/teal_200"app:learn_text="测试测试测试测试" /><com.yl.pictureeditordemo.ui.view.LearnViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="60dp"android:layout_marginTop="20dp"android:layout_marginBottom="20dp"android:background="@color/teal_200"app:learn_text="测试" /></com.yl.pictureeditordemo.ui.view.LearnViewGroup></LinearLayout>

四、到此为止最基本的自定义知识就完了

后面一切自定义控件都在上面的基础之上加工,比如自定义ViewPager,需要用到手势滑动等

五、最后就要考虑性能问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/505967.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CTFHUB--文件包含漏洞--RCE

文件包含漏洞 文件包含漏洞也是一种注入型漏洞&#xff0c;其本质就是输入一段用户能够控制的脚本或者代码&#xff0c;并让服务端执行。有时候由于网站功能需求&#xff0c;会让前端用户选择要包含的文件&#xff0c;而开发人员又没有对要包含的文件进行安全考虑&#xff0c;…

凌特杯,第二届,数字音频传输。simulink matlab

终于比赛进入了尾声&#xff0c;最为指导老师也是非常的激动。接下来进入了论文写作阶段和视频拍摄阶段。 第二届凌特杯规定的硬件是ADI的Pluto&#xff0c;成本在2k以内&#xff0c;能支持MATLAB&#xff0c;它能够流畅的实时播放接收到的音乐数据&#xff0c;并把数据保存成…

为什么要在业务系统中引入大宽表?

在高度系统化驱动的业务中&#xff0c;查看业务报表已经是一个很常见的需求了。在分工非常明确的大型企业里&#xff0c;往往有专门的数据分析团队 BI 或者数据开发团队&#xff0c;他们能够胜任此类需求&#xff08;但也未必是轻松的&#xff0c;或者说高效的&#xff09;。 …

14-Linux部署Hadoop集群

Linux部署Hadoop集群 简介 1&#xff09;Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 2&#xff09;主要解决&#xff0c;海量数据的存储和海量数据的分析计算问题。 Hadoop HDFS 提供分布式海量数据存储能力 Hadoop YARN 提供分布式集群资源管理能力 Hadoop…

【双指针】删除有序数组中重复元素,双指针原地修改数组

删除有序数组中重复元素 链接 . - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/remove-duplicates-from-sorted-array/…

2024.03.01作业

1. 基于UDP的TFTP文件传输 #include "test.h"#define SER_IP "192.168.1.104" #define SER_PORT 69 #define IP "192.168.191.128" #define PORT 9999enum mode {TFTP_READ 1,TFTP_WRITE 2,TFTP_DATA 3,TFTP_ACK 4,TFTP_ERR 5 };void get_…

Java 石头剪刀布小游戏

一、任务 编写一个剪刀石头布游戏的程序。程序启动后会随机生成1~3的随机数&#xff0c;分别代表剪刀、石头和布&#xff0c;玩家通过键盘输入剪刀、石头和布与电脑进行5轮的游戏&#xff0c;赢的次数多的一方为赢家。若五局皆为平局&#xff0c;则最终结果判为平局。 二、实…

项目运维方案

1. 文档介绍 2. 人员与责任 3. 运维过程内容 4. 运维资源 5. 运维服务规划保障 6. 事件处置 7. 质量改进 8. 运维边界及内容 软件开发全套资料获取&#xff1a;软件开发全套资料_数字中台建设指南-CSDN博客

Redis安全加固策略:配置文件权限设置 配置本地日志存储目录 连接超时时间限制

Redis安全加固策略&#xff1a;配置文件权限设置 & 配置本地日志存储目录 & 连接超时时间限制 1.1 配置文件权限设置1.2 配置本地日志存储目录1.3 连接超时时间限制 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1.1 配置文件权限…

(六)Dropout抑制过拟合与超参数的选择--九五小庞

过拟合 即模型在训练集上表现的很好&#xff0c;但是在测试集上效果却很差。也就是说&#xff0c;在已知的数据集合中非常好&#xff0c;再添加一些新数据进来效果就会差很多 欠拟合 即模型在训练集上表现的效果差&#xff0c;没有充分利用数据&#xff0c;预测准确率很低&a…

Docker使用数据卷自定义镜像Dockerfile

文章目录 一、数据卷二、Dockerfile自定义centos 一、数据卷 数据卷(Data Volumes)是一个可供一个或多个容器使用的特殊目录&#xff0c;它将主机操作系统目录直接映射进容器&#xff0c;它可以提供很多有用的特性&#xff1a; 1.数据卷 可以在容器之间共享和重用 2.对数据卷的…

独立游戏《星尘异变》UE5 C++程序开发日志1——项目与代码管理

写在前面&#xff1a;本日志系列将会向大家介绍在《星尘异变》这款模拟经营游戏&#xff0c;在开发时用到的与C相关的泛用代码与算法&#xff0c;主要记录UE5C与原生C的用法区别&#xff0c;以及遇到的问题和解决办法&#xff0c;因为这是我本人从ACM退役以后第一个从头开始的项…