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

自定义ViewGroup-流式布局FlowLayout(重点:测量和布局)

效果

child按行显示,显示不下就换行。


分析

  • 继承ViewGroup
  • onDraw()不重写,使用ViewGroup的
  • 测量-重点 (测量child、测量自己)
  • 布局-重点 (布局child)

知识点

执行顺序

构造函数 -> onMeasure() -> onLayout() -> onDraw()

问:onMeasure()后getMeasuredHeight()和getMeasuredWidth()可以获得到值。

答:因为onMeasure()中会使用setMeasuredDimension(width,height)设置宽高值。

问:onLayout() 后getHeight()和getWidth()可以获得到值

答:getWidth()是使用onLayout() 后的left、right得到的,没有布局的时候是没有left、right值的,getHeight()同理。


onMeasure()度量

  • MeasurSpec类

32位整型数据,高两位是模式,低30位是宽/高数据,用位运算来获取数据。(一个数据分为两部分)

模式: EXACTLY(确定的值)、AT_MOST(需要多少给多少,最多不能超过低30位的数据)、UNSPECIFIED(不指定,滚动的时候)

用于在向下执行测量的时候传递View能用的宽/高数据。

MeasurSpec值是根据父容器和自己LayoutParam分配给View的大小,View需要再onMeasure()时确定自己需要的大小(允许你自己调整),然后设置。

  • 如何获取MeasurSpec值?(LayoutParam转化为px)

View的层级是树形的,度量是递归实现的,child的度量是由father分发的,想要知道MeasurSpec值是如何获取的?可以看ViewGroup中的度量child时,是如何获得child的MeasurSpec值的。

ViewGroup类中提供了getChildMeasureSpec方法,用于获得child的MeasurSpec。

方法参数说明如下:

spec :父布局的MeasurSpec

padding:父布局的padding,如获取child宽度的MeasurSpec,就需要paddingLeft+paddingRight。

childDimension:child的布局,有xxdp/wrap_content/match_parent三种情况,如获取child宽度的MeasurSpec值,就是child布局中的android:layout_width值。

经过对getChildMeasureSpec()源码的分析得出如下规则:(宽高都使用此规则)


  • View的onMeasure()

        1. 据MeasureSpec的不同模式确定自己的宽高

                如果是MeasureSpec.EXACTLY ,使用MeasureSpec中的size

                如果是MeasureSpec.AT_MOST,使用自身需要的大小

                如果是MeasureSpec.UNSPECIFIED,0/自身需要的大小

        2. 设置View的宽高setMeasuredDimension(width,height)


  • ViewGroup的onMeasure()

        除了 View的onMeasure()中要做的,还要度量child。

        先度量谁?自己/child?

        一般都是先度量child,在度量自己,ViewPager除外,ViewPager高度设置为wrap_content无效。


流式布局

  • 度量child

  • 度量自己

如果是MeasureSpec.EXACTLY ,使用MeasureSpec中的size,不用计算。

如果是MeasureSpec.AT_MOST,使用自身需要的大小(child撑起的宽高)。

如果是MeasureSpec.UNSPECIFIED,0/自身需要的大小(child撑起的宽高)。

根据上面规则可知,要计算出child撑起的宽高。

child撑起的宽度(width) = 单行总宽度最大值(包含水平间隔) + paddingLeft + paddingRight

child撑起的高度(height) = 每行中高度最高的child的高度 + 垂直间隔 + paddingTop + paddingBottom

设置初始值

int height = getPaddingTop()+getPaddingBottom();

int width = getPaddingLeft()+getPaddingRight();

循环child,记录单行的数据

int lineHeight = 0; //记录每行的高度 放入一个child的时候对比取最大值

int curWidth = getPaddingLeft()+getPaddingRight(); //记录每行的当前宽度 放入一个child的时候加上child的宽度以及水平间隔

换行的时候,保存单行数据至width和height,并清空单行数据,注意换行的判断条件。

注意最后一行(执行到最后一个元素时,保存最后一行的数据)。

另外,为了方便布局,记录每行的View以及每行的高度,布局时不需要再次计算。

另设置自己的宽高的时候,记得用规则判断下。

具体实现见文章底部源码。

  • 布局

根据测量的宽高,确定child的位置(left、right、top、bottom)

在自定义ViewGroup中布局child的时候,使用的是视图坐标系。

在布局时获取child的宽高使用getMeasuredWidth()/getMeasuredHeight(),此时getWidth()/getHeight()还没有数值。

自定义ViewGroup流程

扩展

  • ViewPager高度设置为wrap_content无效的原因?

在度量时没有先度量child,先设置了自己的宽高,宽高获取使用的是getDefaultSize()方法。

根据文中的获取child的MeasureSpec的规则可知,当LayoutParam的值为wrap_content时,其MeasureSpec的mode为AI_MOST。

看上面源码可知,当model=MeasureSpec.AT_MOST时,没有使用根据child计算高度,用的是父布局能给的所有高度,所以当高度设置为wrap_content,高度仍是占满了父布局的全部。

  • 资料

  • MeasureSpec.UNSPECIFIED说明:https://www.cnblogs.com/liushilin/p/11055741.html
  • google官方提供的流式布局 flexbox-layout

                看的时候注重两点,如何测量子布局child.measure和

                设置自己宽高的位置setMeasuredDimension

                github地址:https://github.com/google/flexbox-layout

                使用文档:FlexboxLayout全攻略(Google官方灵活实现流式布局控件)-CSDN博客

                注意:在真实项目中,可以使用FlexboxLayout实现流式布局,也可使用RecyclerView+FlexboxLayoutManager实现。

  • 可以自适应child高度的ViewPager(自定义ViewPager,具体实现见源码

源码

FlowLayout.java

package com.learn.customui.custom;import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;import java.util.ArrayList;
import java.util.List;/*** 问题:* 1.没有考虑child的margin* 2.宽度多了一个水平间隔* 3.未处理child的visiable属性* 4.没有考虑gravity*/
public class FlowLayout extends ViewGroup {private int mHorizontalSpace = 10; //px 水平间隔private int mVerticalSpace = 10; //px 垂直间隔private List<List<View>> mAllViews = new ArrayList<>();//按行存储View,用于布局使用private List<Integer> lineHeights = new ArrayList<>(); //存储每行的高度public FlowLayout(Context context) {super(context);}public FlowLayout(Context context, AttributeSet attrs) {super(context, attrs);}public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}/**** @param widthMeasureSpec 根据该View父布局的宽度(MeasureSpec)与自身的LayoutParam(android:layout_width)结合获得的MeasureSpec类型值* @param heightMeasureSpec  根据该View父布局的高度(MeasureSpec)与自身的LayoutParam(android:layout_height)结合获得的MeasureSpec类型值**/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);//会多次测量,使用最后一次测量mAllViews.clear();lineHeights.clear();/*** 1 度量Child* 1.1 度量child* 1.2 度量自己的时候需要child的宽高* 重点:使用getChildMeasureSpec()获取child的MeasureSpec (规则就是固定的,至于能不能显示开发者自定)*/for(int i = 0;i<getChildCount();i++){View child = getChildAt(i);//获取child宽度的MeasureSpecint childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,getPaddingLeft()+getPaddingRight(),child.getLayoutParams().width);//获取child高度的MeasureSpecint childHeightMeasureSpec= getChildMeasureSpec(heightMeasureSpec,getPaddingTop()+getPaddingBottom(),child.getLayoutParams().height);//测量childchild.measure(childWidthMeasureSpec,childHeightMeasureSpec);}//child被度量过,可以获取宽高/*** 2 度量自己   根据不同模式下设置不同的大小* MeasureSpec.EXACTLY  使用方法参数中的size* MeasureSpec.AT_MOST  使用子布局撑起来的size* MeasureSpec.UNSPECIFIED  使用方法参数中的size  0/size 0代表不指定(滚动时)*///child撑起的高度 = 每行中高度最高的child的高度 + 垂直间隔 + paddingTop + paddingBottomint height = getPaddingTop()+getPaddingBottom();//child撑起的宽度 = 单行总宽度最大值(包含水平间隔) + paddingLeft + paddingRightint width = getPaddingLeft()+getPaddingRight();//当前View能用的最大宽度(父亲给的)int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);//记录每行的高度int lineHeight = 0;//记录每行的当前宽度int curWidth = getPaddingLeft()+getPaddingRight();//记录每行的child  布局时使用List<View> lineView = new ArrayList<>();//遍历child 计算高度和宽度for(int i = 0;i<getChildCount();i++){View child = getChildAt(i);//换行if(curWidth+child.getMeasuredWidth()>widthSpecSize){//存储当前行的数据mAllViews.add(lineView);lineView = new ArrayList<>();lineHeights.add(lineHeight);height += lineHeight + mVerticalSpace;width = Math.max(width,curWidth);//清空lineHeight = 0;curWidth = getPaddingLeft()+getPaddingRight();}//放入childlineHeight = Math.max(lineHeight,child.getMeasuredHeight());curWidth += child.getMeasuredWidth()+mHorizontalSpace;lineView.add(child);//最后一个child 存储当前行数据if(i == getChildCount()-1){//最后一行不加垂直间隔height += lineHeight;width = Math.max(width,curWidth);mAllViews.add(lineView);lineHeights.add(lineHeight);}}if(MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) width= MeasureSpec.getSize(widthMeasureSpec);if(MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) height = MeasureSpec.getSize(heightMeasureSpec);//设置自己的宽高setMeasuredDimension(width,height);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int curLeft = getPaddingLeft();int curTop = getPaddingTop();for (int i = 0; i < mAllViews.size(); i++) {for (View child : mAllViews.get(i)) {child.layout(curLeft,curTop,curLeft+child.getMeasuredWidth(),curTop+child.getMeasuredHeight());curLeft += child.getMeasuredWidth()+mHorizontalSpace;}curLeft = getPaddingLeft();curTop += lineHeights.get(i)+mVerticalSpace;}}
}

activity_flow.xml

<?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"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".FlowActivity"><com.learn.customui.custom.FlowLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/black"><TextViewandroid:layout_width="100dp"android:layout_height="50dp"android:gravity="center"android:background="@color/red"android:text="1111"/><TextViewandroid:layout_width="300dp"android:layout_height="50dp"android:gravity="center"android:background="@color/red"android:text="2222"/><TextViewandroid:layout_width="100dp"android:layout_height="50dp"android:gravity="center"android:background="@color/red"android:text="1111"/><TextViewandroid:layout_width="100dp"android:layout_height="50dp"android:gravity="center"android:background="@color/red"android:text="2222"/><TextViewandroid:layout_width="100dp"android:layout_height="50dp"android:gravity="center"android:background="@color/red"android:text="1111"/><TextViewandroid:layout_width="100dp"android:layout_height="50dp"android:gravity="center"android:background="@color/red"android:text="2222"/></com.learn.customui.custom.FlowLayout></LinearLayout>

WrapHeightViewPager.java

package com.learn.customui.custom;import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.ViewPager;public class WrapHeightViewPager extends ViewPager {public WrapHeightViewPager(@NonNull Context context) {super(context);}public WrapHeightViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);/*** 方法1:在super前改变heightMeasureSpec中size(targetSDK = Android33,此方法不使用,获取到的child=null,targetSDK=28 可用,其余版本未测试)* 1.如何改变MeasureSpec中的size?使用MeasureSpec.makeMeasureSpec(size,mode)重新生成一个。* 2.获取高度mode的方法?使用MeasureSpec.getMode(heightMeasureSpec)/设置为固定的MeasureSpec.EXACTLY** 方法2:在super后重新设置高度(不存在方法1的问题)setMeasuredDimension(getMeasuredWidth(),height);* 问题:* 1.宽度使用 getMeasuredWidth(),已在super中设置过。** 共同问题:* 1.高度size怎么获取?child中最高的?* 循环遍历child,使用所有child中高度最高的(适合child高度统一的情况)* 2.当前child的高度?如何获取当前child,切换child的时候会重新onMeasure()吗?(当child高度不统一,需要再切换的时候重新设置时)(待验证,会有很多坑)* getChildAt(getCurrentItem())获取当前child,注意:切换的时候会销毁其他,注意越界问题。* 如果不会重新onMeasure(),可以自定义方法自行刷新。*///此处使用方法2实现for (int i = 0; i < getChildCount(); i++) {View child = getChildAt(i);ViewGroup.LayoutParams lp = child.getLayoutParams();int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, getPaddingLeft() + getPaddingRight(), lp.width);int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, getPaddingTop() + getPaddingBottom(), lp.height);child.measure(childWidthMeasureSpec,childHeightMeasureSpec);}int height = 0;int heightSize = MeasureSpec.getSize(heightMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);switch (heightMode){case MeasureSpec.EXACTLY:height = heightSize;break;case MeasureSpec.AT_MOST:case MeasureSpec.UNSPECIFIED:for (int i = 0; i < getChildCount(); i++) {View child = getChildAt(i);height = Math.max(height,child.getMeasuredHeight());}break;}setMeasuredDimension(getMeasuredWidth(),height);}
}

相关文章:

自定义ViewGroup-流式布局FlowLayout(重点:测量和布局)

效果 child按行显示&#xff0c;显示不下就换行。 分析 继承ViewGrouponDraw()不重写&#xff0c;使用ViewGroup的测量-重点 &#xff08;测量child、测量自己&#xff09;布局-重点 &#xff08;布局child&#xff09; 知识点 执行顺序 构造函数 -> onMeasure() -> …...

C++的入门基础(二)

目录 引用的概念和定义引用的特性引用的使用const引用指针和引用的关系引用的实际作用inlinenullptr 引用的概念和定义 在语法上引用是给一个变量取别名&#xff0c;和这个变量共用同一块空间&#xff0c;并不会给引用开一块空间。 取别名就是一块空间有多个名字 类型& …...

显示产业如何突破芯片短板

尽管中国在显示IC领域面临一定的不足&#xff0c;但新技术的不断涌现为中国企业提供了重要的发展机遇。随着手机、平板电脑和液晶电视对显示屏性能要求的不断提高&#xff0c;显示驱动IC也必须相应地发展&#xff0c;向更高分辨率、更大尺寸和更低功耗的方向迈进。例如&#xf…...

STM32HAL库+ESP8266+cJSON+微信小程序_连接华为云物联网平台

STM32HAL库ESP8266cJSON微信小程序_连接华为云物联网平台 实验使用资源&#xff1a;正点原子F407 USART1&#xff1a;PA9P、A10&#xff08;串口打印调试&#xff09; USART3&#xff1a;PB10、PB11&#xff08;WiFi模块&#xff09; DHT11&#xff1a;PG9&#xff08;采集数据…...

debian或Ubuntu中开启ssh允许root远程ssh登录的方法

debian或Ubuntu中开启ssh允许root远程ssh登录的方法 前因&#xff1a; 因开发需要&#xff0c;需要设置开发板的ssh远程连接。 操作步骤如下&#xff1a; 安装openssh-server sudo apt install openssh-server设置root用户密码&#xff1a; sudo passwd root允许root用户…...

C++《日期》实现

C《日期》实现 头文件实现文件 头文件 在该文件中是为了声明函数和定义类成员 using namespace std; class Date {friend ostream& operator<<(ostream& out, const Date& d);//友元friend istream& operator>>(istream& cin, Date& d);//…...

【面试题】MySQL(第三篇)

目录 1. MySQL中如何处理死锁&#xff1f; 2. MySQL中的主从复制是如何实现的&#xff1f; 3. MySQL中的慢查询日志是什么&#xff1f;如何使用它来优化性能&#xff1f; 4.存储过程 一、定义与基本概念 二、特点与优势 三、类型与分类 四、创建与执行 五、示例 六、总…...

tensorflow之欠拟合与过拟合,正则化缓解

过拟合泛化性弱 欠拟合解决方法&#xff1a; 增加输入特征项 增加网络参数 减少正则化参数 过拟合的解决方法&#xff1a; 数据清洗 增大训练集 采用正则化 增大正则化参数 正则化缓解过拟合 正则化在损失函数中引入模型复杂度指标&#xff0c;利用给w增加权重&#xff0c;…...

vue实现a-model弹窗拖拽移动

通过自定义拖拽指令实现 实现效果 拖动顶部&#xff0c;可对整个弹窗实施拖拽&#xff08;如果需要拖动底部、中间内容实现拖拽&#xff0c;把下面的ant-modal-header对应改掉就行&#xff09; 代码实现 编写自定义指令 新建一个ts / js文件&#xff0c;用ts举例 import V…...

速盾:如何加强网站的安全性

随着互联网的快速发展&#xff0c;网站的安全性变得越来越重要。CDN&#xff08;内容分发网络&#xff09;是一种常见的网络加速服务&#xff0c;它可以将网站的静态内容分发到全球各地的服务器上&#xff0c;以提供更快的访问速度。然而&#xff0c;CDN 也存在一些安全风险&am…...

【PyTorch单点知识】自动求导机制的原理与实践

文章目录 0. 前言1. 自动求导的基本原理2. PyTorch中的自动求导2.1 创建计算图2.2 反向传播2.3 反向传播详解2.4 梯度清零2.5 定制自动求导 3. 代码实例&#xff1a;线性回归的自动求导4. 结论 0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己学习的理解&…...

【Java】搜索引擎设计:信息搜索怎么避免大海捞针?

一、内容分析 我们准备开发一个针对全网内容的搜索引擎&#xff0c;产品名称为“Bingoo”。 Bingoo的主要技术挑战包括&#xff1a; 针对爬虫获取的海量数据&#xff0c;如何高效地进行数据管理&#xff1b;当用户输入搜索词的时候&#xff0c;如何快速查找包含搜索词的网页…...

【Python】ModuleNotFoundError: No module named ‘distutils.util‘ bug fix

【Python】ModuleNotFoundError: No module named distutils.util bug fix 1. error like this2. how to fix why this error occured , because i remove the origin version python of ubuntu of 20.04. then the system trapped in tty1 , you must make sure the laptop li…...

痉挛性斜颈对生活有哪些影响?

痉挛性斜颈&#xff0c;这个名字听起来可能并不熟悉&#xff0c;但它实际上是一种神经系统疾病&#xff0c;影响着全球数百万人的生活质量。它以一种无法控制的方式&#xff0c;使患者的颈部肌肉发生不自主的收缩&#xff0c;导致头部姿势异常。对于患者来说&#xff0c;痉挛性…...

Javassist 修改 jar 包里的 class 文件

前言 Javassist 是一个用于处理 Java 字节码的类库&#xff0c;可以用以修改 class 文件或 jar 包里的 class 文件。 简单来说我们用Java编写的代码是放在 java 格式的代码文件里&#xff0c;在编译的时候会编译为 class 格式的字节码文件&#xff0c;然后一般所有 class 文件…...

交换机的二三层原理

相同VLAN的交换机交换原理&#xff08;二层交换原理&#xff09;&#xff1a; 交换机收到数据帧&#xff0c;首先会检查数据帧的VLAN标签和目标MAC&#xff0c;若属于相同VLAN&#xff0c;且该目标MAC在本地MAC表中&#xff0c;则直接根据出接口进行数据转发 不同VLAN的交换机…...

HarmonyOS ArkUi 字符串<展开/收起>功能

效果图&#xff1a; 官方API&#xff1a; ohos.measure (文本计算) 方式一 measure.measureTextSize 跟方式二使用一样&#xff0c;只是API调用不同&#xff0c;可仔细查看官网方式二 API 12 import { display, promptAction } from kit.ArkUI import { MeasureUtils } fr…...

Lianwei 安全周报|2024.07.09

新的一周又开始了&#xff0c;以下是本周「Lianwei周报」&#xff0c;我们总结推荐了本周的政策/标准/指南最新动态、热点资讯和安全事件&#xff0c;保证大家不错过本周的每一个重点&#xff01; 政策/标准/指南最新动态 01 《数字中国发展报告&#xff08;2023年&#xff09…...

火遍全网的15个Python的实战项目,你该不会还不知道怎么用吧!

经常听到有朋友说&#xff0c;学习编程是一件非常枯燥无味的事情。其实&#xff0c;大家有没有认真想过&#xff0c;可能是我们的学习方法不对&#xff1f; 比方说&#xff0c;你有没有想过&#xff0c;可以通过打游戏来学编程&#xff1f; 今天我想跟大家分享几个Python小游…...

快速使用BRTR公式出具的大模型Prompt提示语

Role:文章模仿大师 Background: 你是一位文章模仿大师&#xff0c;擅长分析文章风格并进行模仿创作。老板常让你学习他人文章后进行模仿创作。 Attention: 请专注在文章模仿任务上&#xff0c;提供高质量的输出。 Profile: Author: 一博Version: 1.0Language: 中文Descri…...

Xilinx FPGA DDR4 接口的 PCB 准则

目录 1. 简介 1.1 FPGA-MIG 与 DDR4 介绍 1.2 DDR4 信号介绍 1.2.1 Clock Signals 1.2.2 Address and Command Signals 1.2.3 Control Signals 1.2.4 Data Signals 1.2.5 Other Signals 2. 通用存储器布线准则 3. Xilinx FPGA-MIG 的 PCB 准则 3.1 引脚配置 3.1.1 …...

神经网络 | Transformer 基本原理

目录 1 为什么使用 Transformer&#xff1f;2 Attention 注意力机制2.1 什么是 Q、K、V 矩阵&#xff1f;2.2 Attention Value 计算流程2.3 Self-Attention 自注意力机制2.3 Multi-Head Attention 多头注意力机制 3 Transformer 模型架构3.1 Positional Encoding 位置编…...

浅析 VO、DTO、DO、PO 的概念

文章目录 I 浅析 VO、DTO、DO、PO1.1 概念1.2 模型1.3 VO与DTO的区别I 浅析 VO、DTO、DO、PO 1.1 概念 VO(View Object) 视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。DTO(Data Transfer Object): 数据传输对象,这个概念来源于J2EE的设…...

7.8 CompletableFuture

Future 接口理论知识复习 Future 接口&#xff08;FutureTask 实现类&#xff09;定义了操作异步任务执行的一些方法&#xff0c;如获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕等。 比如主线程让一个子线程去执行任务&#xff0c;子线…...

iPad锁屏密码忘记怎么办?有什么方法可以解锁?

当我们在日常使用iPad时&#xff0c;偶尔可能会遇到忘记锁屏密码的尴尬情况。这时&#xff0c;不必过于担心&#xff0c;因为有多种方法可以帮助您解锁iPad。接下来&#xff0c;小编将为您详细介绍这些解决方案。 一、使用iCloud的“查找我的iPhone”功能 如果你曾经启用了“查…...

了解并缓解 IP 欺骗攻击

欺骗是黑客用来未经授权访问计算机或网络的一种网络攻击&#xff0c;IP 欺骗是其他欺骗方法中最常见的欺骗类型。通过 IP 欺骗&#xff0c;攻击者可以隐藏 IP 数据包的真实来源&#xff0c;使攻击来源难以知晓。一旦访问网络或设备/主机&#xff0c;网络犯罪分子通常会挖掘其中…...

java LogUtil输出日志打日志的class文件内具体方法和行号

最近琢磨怎么把日志打的更清晰&#xff0c;方便查找问题&#xff0c;又不需要在每个class内都创建Logger对象&#xff0c;还带上不同的颜色做区分&#xff0c;简直不要太爽。利用堆栈的方向顺序拿到日志的class问题。看效果&#xff0c;直接上代码。 1、demo test 2、输出效果…...

02. Hibernate 初体验之持久化对象

1. 前言 本节课程让我们一起体验 Hibernate 的魅力&#xff01;编写第一个基于 Hibernate 的实例程序。 在本节课程中&#xff0c;你将学到 &#xff1a; Hibernate 的版本发展史&#xff1b;持久化对象的特点。 为了更好地讲解这个内容&#xff0c;这个初体验案例分上下 2…...

MySQL超详细学习教程,2023年硬核学习路线

文章目录 前言1. 数据库的相关概念1.1 数据1.2 数据库1.3 数据库管理系统1.4 数据库系统1.5 SQL 2. MySQL数据库2.1 MySQL安装2.2 MySQL配置2.2.1 添加环境变量2.2.2 新建配置文件2.2.3 初始化MySQL2.2.4 注册MySQL服务2.2.5 启动MySQL服务 2.3 MySQL登录和退出2.4 MySQL卸载2.…...

初识SpringBoot

1.Maven Maven是⼀个项⽬管理⼯具, 通过pom.xml⽂件的配置获取jar包&#xff0c;⽽不⽤⼿动去添加jar包 主要功能 项⽬构建管理依赖 构建Maven项目 1.1项目构建 Maven 提供了标准的,跨平台(Linux, Windows, MacOS等)的⾃动化项⽬构建⽅式 当我们开发了⼀个项⽬之后, 代…...

什么网站做简历/电商运营多少钱一个月

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2020建筑电工(建筑特殊工种)考试题库及建筑电工(建筑特殊工种)模拟考试&#xff0c;包含建筑电工(建筑特殊工种)考试题库答案解析及建筑电工(建筑特殊工种)模拟考试练习。由安全生产模拟考试一点通公众号结合国家建筑…...

wordpress 文章关联/广告推广费用一般多少

[JLOI2011]飞行路线 二维spfa&#xff0c;不过需要优化&#xff0c;用优先队列比较快&#xff0c;手打普通队列应该也可以 #include<iostream> #include<cstdio> #include<cstring> #include<queue> #define maxn 10005 using namespace std; int n,m,…...

网站建设后怎么/注册网址

1.HashSet存储字符串并遍历 * 特点&#xff1a;无序、无索引、无重复 HashSet存储字符串并遍历HashSet<String> hs new HashSet<>();hs.add("a");hs.add("b");hs.add("a");hs.add("c");hs.add("c");hs.add(&qu…...

300m空间够用吗 wordpress/深圳专业seo

noVNC介绍VNC的客户端很多&#xff0c;比如VNC Viewer、TightVNC、RealVNC、UltraVNC等VNC的客户端,可以使用SSH以及VNC的方式来登录及管理QEMU、KVM、libvirt虚拟机&#xff0c; 那有没有通过Web的方式去登录及管理QEMU、KVM、libvirt虚拟机呢&#xff0c;noVNC就是其中一种方…...

莆田建站培训/seo网站优化方案摘要

为什么80%的码农都做不了架构师&#xff1f;>>> centos7下spark-2.3.0集群搭建 环境准备 1.服务器概览 hostnameip说明node1.spark192.168.2.140node1r节点(master)node2.spark192.168.2.141node2节点node3.spark192.168.2.142node3节点分别在三台服务器上执行以下…...

政府网站建设/女教师遭网课入侵直播录屏曝光se

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客QQ群&#xff1a;1040082875 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前文 今天给大家介绍一款3D动画制作软件&…...