【Android面试】View绘制流程专题

文章目录

  • 一、基础原理与流程
    • [1. 简述Android中View的完整绘制流程(从顶层View到子View),并说明performTraversals()在其中的作用。**](#1. 简述Android中View的完整绘制流程(从顶层View到子View),并说明performTraversals()在其中的作用。**)
    • [2. View的绘制流程(measure、layout、draw)是自上而下还是自下而上的?请分别说明三个流程的遍历顺序。](#2. View的绘制流程(measure、layout、draw)是自上而下还是自下而上的?请分别说明三个流程的遍历顺序。)
    • [3. invalidate()、postInvalidate()、requestLayout()三者的区别是什么?分别会触发View绘制流程的哪些阶段?**](#3. invalidate()、postInvalidate()、requestLayout()三者的区别是什么?分别会触发View绘制流程的哪些阶段?**)
    • [4. 什么是MeasureSpec?它由哪两部分组成?EXACTLY、AT_MOST、UNSPECIFIED三种模式分别对应什么场景?**](#4. 什么是MeasureSpec?它由哪两部分组成?EXACTLY、AT_MOST、UNSPECIFIED三种模式分别对应什么场景?**)
    • [5. ViewGroup和普通View在measure过程中有什么本质区别?](#5. ViewGroup和普通View在measure过程中有什么本质区别?)
    • [6. onLayout(boolean changed, int l, int t, int r, int b)方法中的changed参数代表什么含义?](#6. onLayout(boolean changed, int l, int t, int r, int b)方法中的changed参数代表什么含义?)
  • 二、源码深度与细节
    • [1. ViewRootImpl、DecorView、Window三者之间的关系是什么?View的绘制是由谁发起的?](#1. ViewRootImpl、DecorView、Window三者之间的关系是什么?View的绘制是由谁发起的?)
    • [2. 为什么View的measure过程可能会执行多次?什么情况下会导致多次measure?](#2. 为什么View的measure过程可能会执行多次?什么情况下会导致多次measure?)
    • [3. 简述draw()方法的执行流程(包含绘制背景、绘制自己、绘制子View、绘制前景等步骤)。](#3. 简述draw()方法的执行流程(包含绘制背景、绘制自己、绘制子View、绘制前景等步骤)。)
    • [4. setWillNotDraw(boolean willNotDraw)这个方法的作用是什么?设置为true或false对绘制流程有什么影响?](#4. setWillNotDraw(boolean willNotDraw)这个方法的作用是什么?设置为true或false对绘制流程有什么影响?)
    • [5. View的getMeasuredWidth()和getWidth()有什么区别?分别在什么时机可以获取到正确的值?**](#5. View的getMeasuredWidth()和getWidth()有什么区别?分别在什么时机可以获取到正确的值?**)
    • [6. 当View的宽高设置为wrap_content时,若不重写onMeasure()会出现什么问题?底层源码是如何处理的?**](#6. 当View的宽高设置为wrap_content时,若不重写onMeasure()会出现什么问题?底层源码是如何处理的?**)
    • [7. 简述Choreographer的作用,它是如何协调VSYNC信号与View绘制的?**](#7. 简述Choreographer的作用,它是如何协调VSYNC信号与View绘制的?**)
  • 三、性能优化与卡顿
    • [1. 过度绘制(Overdraw)产生的原因是什么?如何通过工具检测并优化?**](#1. 过度绘制(Overdraw)产生的原因是什么?如何通过工具检测并优化?**)
    • [2 . 什么是View的刷新机制?频繁调用invalidate()会导致什么问题?如何避免?](#2 . 什么是View的刷新机制?频繁调用invalidate()会导致什么问题?如何避免?)
    • [3. 为什么不建议在onDraw()方法中执行耗时操作或创建对象?**](#3. 为什么不建议在onDraw()方法中执行耗时操作或创建对象?**)
    • [4. HardwareAcceleration(硬件加速)对View的绘制流程有什么影响?开启硬件加速后,onDraw()有哪些方法不能使用?](#4. HardwareAcceleration(硬件加速)对View的绘制流程有什么影响?开启硬件加速后,onDraw()有哪些方法不能使用?)
    • [5. 简述UI渲染的16ms原理,丢帧(Frame Drop)与View绘制流程的关系。**](#5. 简述UI渲染的16ms原理,丢帧(Frame Drop)与View绘制流程的关系。**)
    • [6. 什么是布局嵌套过深?它如何影响measure和layout流程?如何优化?](#6. 什么是布局嵌套过深?它如何影响measure和layout流程?如何优化?)
  • 四、异常场景与边界问题(百度/阿里爱考)
    • [1. 在onCreate()方法中为什么获取不到View的宽高?有哪些解决方案?**](#1. 在onCreate()方法中为什么获取不到View的宽高?有哪些解决方案?**)
    • [2. 当一个View设置了GONE或INVISIBLE时,它是否会参与measure和layout流程?](#2. 当一个View设置了GONE或INVISIBLE时,它是否会参与measure和layout流程?)
    • [3. ScrollView嵌套ListView/RecyclerView为什么会出现测量问题?根本原因是什么?](#3. ScrollView嵌套ListView/RecyclerView为什么会出现测量问题?根本原因是什么?)
    • [4. 自定义View时,requestDisallowInterceptTouchEvent()与View的绘制流程是否有关联?](#4. 自定义View时,requestDisallowInterceptTouchEvent()与View的绘制流程是否有关联?)
    • [5. 简述View的forceLayout()标记的作用,它是如何影响measure流程的?](#5. 简述View的forceLayout()标记的作用,它是如何影响measure流程的?)
  • 五、自定义View实战(综合考察)
    • [1. 自定义ViewGroup时,必须重写哪两个方法?为什么?**](#1. 自定义ViewGroup时,必须重写哪两个方法?为什么?**)
    • [2. 自定义View实现圆形图片,在onDraw()中需要注意哪些绘制流程上的细节?**](#2. 自定义View实现圆形图片,在onDraw()中需要注意哪些绘制流程上的细节?**)
    • [3. 如何实现一个支持宽高自适应(wrap_content)的自定义View?](#3. 如何实现一个支持宽高自适应(wrap_content)的自定义View?)
    • [4. 在自定义View中,如何正确处理padding和margin属性?**](#4. 在自定义View中,如何正确处理padding和margin属性?**)
    • [5. 当View需要根据内容动态改变大小时,如何正确调用requestLayout()和invalidate()?**](#5. 当View需要根据内容动态改变大小时,如何正确调用requestLayout()和invalidate()?**)
  • [todo:surfaceview canvas画布](#todo:surfaceview canvas画布)

一、基础原理与流程

1. 简述Android中View的完整绘制流程(从顶层View到子View),并说明performTraversals()在其中的作用。**

  • Android View绘制流程始于ViewRootImpl,核心分为三大阶段:measure(测量)、layout(布局)、draw(绘制),整体遵循自上而下的遍历顺序。
  • 完整流程:系统接收到VSYNC信号后,由ViewRootImpl的performTraversals()方法发起绘制,该方法是整个绘制流程的入口和总调度方法。依次调用performMeasure()、performLayout()、performDraw(),分别触发顶层DecorView的测量、布局、绘制,再逐级传递到所有子View,完成整棵View树的绘制。
  • performTraversals()作用:负责初始化绘制参数、判断是否需要重新测量、布局、绘制,协调三大流程的执行时机,控制View树的刷新逻辑,同时处理窗口尺寸变化、界面重绘等触发时机。

2. View的绘制流程(measure、layout、draw)是自上而下还是自下而上的?请分别说明三个流程的遍历顺序。

三大流程整体都是自上而下遍历,父View先完成自身相关逻辑,再调度子View执行。

  • measure流程:父View调用自身measure(),在onMeasure()中根据自身规则,计算并生成子View的MeasureSpec,再调用子View的measure(),逐级传递直到叶子节点;叶子节点测量完成后,回溯确定父View最终宽高。
  • layout流程:父View调用layout()确定自身在父容器中的位置,在onLayout()中遍历子View,调用子View的layout()方法,传入子View的左上右下坐标,确定子View位置。
  • draw流程:父View调用draw()方法,按步骤绘制背景、自身内容、子View,遍历调用子View的draw()方法,完成逐级绘制。

3. invalidate()、postInvalidate()、requestLayout()三者的区别是什么?分别会触发View绘制流程的哪些阶段?**

  • invalidate():在UI线程调用,标记当前View为需要重绘,只会触发draw流程,不会触发measure和layout,适合View尺寸不变、仅内容改变的刷新场景。
  • postInvalidate():作用同invalidate(),可在子线程调用,内部通过Handler切换到UI线程执行invalidate(),适配子线程刷新View的场景。
  • requestLayout():标记View需要重新测量、布局,会逐级向上传递,触发measure流程和layout流程,执行完成后会间接触发draw流程,适合View尺寸、位置发生变化的刷新场景。

4. 什么是MeasureSpec?它由哪两部分组成?EXACTLY、AT_MOST、UNSPECIFIED三种模式分别对应什么场景?**

  • MeasureSpec是View的测量规格,是一个32位的int值,用于父View向子View传递测量规则,约束子View的宽高计算。
  • 组成:高2位代表测量模式SpecMode,低30位代表测量大小SpecSize。
  • EXACTLY(精确模式):父View指定子View确切大小,对应match_parent或固定dp值,子View必须遵循该尺寸。
  • AT_MOST(最大模式):子View尺寸最大不能超过父View剩余空间,对应wrap_content,子View可根据自身内容调整大小,但不能超出上限。
  • UNSPECIFIED(无限制模式):父View不对子View做任何尺寸限制,子View想多大就多大,多用于系统内部控件(如ListView、ScrollView)测量子View,日常开发极少用到。

5. ViewGroup和普通View在measure过程中有什么本质区别?

  • 普通View是单一控件,measure过程只需完成自身尺寸计算,在onMeasure()中调用setMeasuredDimension()设置自身宽高即可。
  • ViewGroup是容器控件,除了计算自身尺寸,更核心的工作是遍历所有子View,计算每个子View的MeasureSpec,调度子View执行measure,测量完所有子View后,再根据子View的宽高和自身规则,确定自身最终宽高。ViewGroup没有重写onMeasure(),需要子类(如LinearLayout、RelativeLayout)自行实现测量逻辑。

6. onLayout(boolean changed, int l, int t, int r, int b)方法中的changed参数代表什么含义?

changed参数表示View的尺寸或位置是否发生变化。

当值为true时,代表当前View相比上次布局,位置或大小发生了改变;当值为false时,代表尺寸和位置无变化,可跳过重复布局逻辑,提升绘制效率。

二、源码深度与细节

1. ViewRootImpl、DecorView、Window三者之间的关系是什么?View的绘制是由谁发起的?

  • Window是抽象类,Android中唯一实现类是PhoneWindow,是Activity的顶级窗口,负责管理界面样式、标题栏、加载布局。
  • DecorView是整个界面的顶层View,是PhoneWindow的内部View,继承自FrameLayout,包含标题栏和内容栏(ContentView),我们setContentView设置的布局就是添加到DecorView的内容栏中。
  • ViewRootImpl是连接WindowManagerService和DecorView的桥梁,负责View的绘制、事件分发、窗口管理,不是View的子类。
  • 三者关系:Activity持有PhoneWindow,PhoneWindow持有DecorView,ViewRootImpl关联DecorView,负责调度DecorView的绘制。
    View绘制由ViewRootImpl的performTraversals()方法发起。

2. 为什么View的measure过程可能会执行多次?什么情况下会导致多次measure?

measure过程执行多次,是因为父View无法一次性确定自身尺寸,需要多次测量子View,回溯调整自身大小。
常见场景:

  • 嵌套使用ScrollView、LinearLayout权重属性、RelativeLayout时,父View需要先测量子View,再根据子View尺寸调整自身,会触发二次measure。
  • View尺寸设置为wrap_content,且依赖子View尺寸时。
  • 动态改变View布局参数,调用requestLayout()后,会重新触发measure流程。
    源码中,多次measure是正常优化逻辑,但过度嵌套会导致多次测量,降低绘制效率。

3. 简述draw()方法的执行流程(包含绘制背景、绘制自己、绘制子View、绘制前景等步骤)。

View的draw()方法是一个标准模板方法,执行步骤固定,不可轻易改写,源码步骤分为6步,核心步骤如下:

  • 绘制背景(drawBackground()):绘制View的背景色、背景图,不可跳过。
  • 保存画布图层(可选):为硬件加速做准备。
  • 绘制自身内容(onDraw()):调用View的onDraw(),绘制控件主体内容,空实现,需子类重写。
  • 绘制子View(dispatchDraw()):ViewGroup重写该方法,遍历子View,调用子View的draw()方法,普通View无此逻辑。
  • 绘制装饰(如滚动条、前景):绘制View的前景、滚动条等装饰元素。
  • 恢复画布图层,完成绘制。

4. setWillNotDraw(boolean willNotDraw)这个方法的作用是什么?设置为true或false对绘制流程有什么影响?

该方法用于标记当前View是否需要执行onDraw()绘制自身内容,是系统针对ViewGroup做的绘制优化。

  • 设置为true:代表该View没有自身内容需要绘制,只会作为容器展示子View,系统会跳过onDraw()方法,减少绘制开销,默认所有ViewGroup都会开启该优化。
  • 设置为false:代表该View需要绘制自身内容,系统会正常执行onDraw()方法。如果自定义ViewGroup需要重写onDraw()绘制内容,必须手动调用setWillNotDraw(false),否则onDraw()不会执行。

5. View的getMeasuredWidth()和getWidth()有什么区别?分别在什么时机可以获取到正确的值?**

  • getMeasuredWidth():获取View测量完成后的宽度,值来自setMeasuredDimension()设置的测量宽度,在measure流程结束后即可获取,代表View期望的宽度。
  • getWidth():获取View最终显示的宽度,值为layout流程中确定的right - left,代表View实际在屏幕上展示的宽度。
    获取时机:两者在onCreate()、onStart()、onResume()中都无法获取正确值,因为此时View还未完成测量和布局。
    正确时机:measure完成后可获取getMeasuredWidth(),layout完成后可获取getWidth(),正常情况下两者数值相等,除非手动改写layout()逻辑。

6. 当View的宽高设置为wrap_content时,若不重写onMeasure()会出现什么问题?底层源码是如何处理的?**

自定义View不重写onMeasure(),宽高设置为wrap_content时,效果会等同于match_parent ,无法自适应内容大小。

源码逻辑:View默认的onMeasure()中,当测量模式为AT_MOST(wrap_content)时,会直接将SpecSize作为自身宽高,而此时SpecSize等于父View可用空间,导致View铺满父容器。

解决方法:重写onMeasure(),针对AT_MOST模式,设置自定义的默认宽高,再调用setMeasuredDimension()完成测量。

7. 简述Choreographer的作用,它是如何协调VSYNC信号与View绘制的?**

答案:Choreographer是Android系统的帧率协调者 ,负责接收系统VSYNC同步信号,调度UI绘制、动画、输入事件等操作,保证界面流畅渲染。

工作流程:

  • 系统每隔16.6ms发出一次VSYNC信号(60fps),Choreographer接收到信号后。
  • 按顺序执行三大任务:输入事件处理、动画执行、View绘制。
  • 触发ViewRootImpl的performTraversals()方法,启动View绘制流程。
    作用:统一调度UI刷新时机,避免频繁刷新导致丢帧,保证界面渲染和系统帧率同步。

三、性能优化与卡顿

1. 过度绘制(Overdraw)产生的原因是什么?如何通过工具检测并优化?**

  • 过度绘制指屏幕上同一个像素点,在一帧内被多次绘制,浪费CPU、GPU资源,严重时导致卡顿丢帧。
  • 产生原因:布局嵌套过深、多个控件重叠、背景重复设置(父View和子View设置相同背景)、自定义View重复绘制。
  • 检测工具:开发者选项中的调试GPU过度绘制工具,通过颜色区分绘制次数:蓝色(1次)、绿色(2次)、浅红(3次)、深红(4次及以上,严重)。
  • 优化方案:
    移除重复背景,只保留顶层背景。
    减少布局嵌套,使用ConstraintLayout扁平化布局。
    自定义View中使用clipRect()屏蔽不可见区域的绘制。
    避免使用多层重叠透明控件。

2 . 什么是View的刷新机制?频繁调用invalidate()会导致什么问题?如何避免?

  • View刷新机制是通过invalidate()/requestLayout()标记View需要重绘或重新布局,等待下一个VSYNC信号到来后,执行对应绘制流程的机制。
  • 频繁调用invalidate()的问题:短时间内多次触发draw流程,占用大量CPU、GPU资源,导致UI线程阻塞,引发界面卡顿、丢帧,甚至内存飙升。
  • 避免方案:
    合并刷新逻辑,减少刷新次数。
    使用postInvalidateOnAnimation(),同步VSYNC信号刷新。
    加入防抖逻辑,避免无意义的重复刷新。
    仅刷新需要改变的局部区域,而非整个View。

3. 为什么不建议在onDraw()方法中执行耗时操作或创建对象?**

onDraw()方法会被频繁调用,只要调用invalidate()就会执行,界面滑动、动画播放时也会触发。

  • 执行耗时操作:会拉长draw流程执行时间,超出16ms阈值,直接导致丢帧、界面卡顿。
  • 创建对象:会频繁分配内存,触发GC回收,GC会暂停UI线程,造成界面卡顿、抖动。
    规范写法:对象初始化、耗时计算放在onDraw()外,如构造方法、onMeasure()中执行。

4. HardwareAcceleration(硬件加速)对View的绘制流程有什么影响?开启硬件加速后,onDraw()有哪些方法不能使用?

硬件加速是通过GPU分担绘制工作,提升绘制效率,Android 4.0后默认开启。

对绘制流程的影响:

  • 绘制效率大幅提升,界面更流畅。
  • 绘制逻辑改为GPU渲染,画布(Canvas)操作方式改变。
  • 部分Canvas API不兼容,会导致绘制异常或闪退。
    不支持的API:clipPath()、clipRegion()、drawPicture()、drawTextOnPath()、setShadowLayer()、drawVertices()等,以及部分滤镜、混合模式操作。遇到不兼容场景,可关闭当前View的硬件加速。

5. 简述UI渲染的16ms原理,丢帧(Frame Drop)与View绘制流程的关系。**

  • Android系统屏幕刷新率为60fps,每隔16.6ms发出一次VSYNC信号,系统需要在16ms内完成一帧画面的测量、布局、绘制,否则会出现丢帧。
  • 丢帧原因:View绘制流程耗时过长,超过16ms阈值,系统无法按时渲染下一帧,导致画面卡顿、掉帧。
  • 关联点:measure/layout嵌套过深、onDraw()耗时、过度绘制、频繁刷新,都会拉长绘制流程,引发丢帧。优化绘制流程,缩减各阶段耗时,保证在16ms内完成,就能避免丢帧。

6. 什么是布局嵌套过深?它如何影响measure和layout流程?如何优化?

布局嵌套过深指多层ViewGroup层层嵌套,导致View树层级过多,属于常见的UI性能问题。

对流程的影响:

  • measure流程:层级越多,遍历次数越多,多次测量会成倍增加耗时。
  • layout流程:逐级确定位置,层级越深,耗时越长。
  • 极易引发丢帧、界面卡顿。

优化方案:

  • 使用ConstraintLayout替代多层嵌套LinearLayout、RelativeLayout。
  • 移除无用的父布局,精简View树层级。
  • 巧用merge标签减少根布局嵌套。
  • 用ViewStub懒加载不常用布局。

四、异常场景与边界问题(百度/阿里爱考)

1. 在onCreate()方法中为什么获取不到View的宽高?有哪些解决方案?**

onCreate()阶段,Activity只是完成了布局加载,ViewRootImpl还未关联DecorView,View的measure、layout流程还没有执行,宽高还未计算,所以获取到的值为0。

解决方案:

  • View.post():post的Runnable会在View绘制完成后执行,可获取宽高。
  • ViewTreeObserver.OnGlobalLayoutListener:监听View全局布局完成事件,回调中获取宽高,记得及时移除监听防止内存泄漏。
  • onWindowFocusChanged():Activity获取焦点时,View已完成绘制,可获取宽高。

2. 当一个View设置了GONE或INVISIBLE时,它是否会参与measure和layout流程?

  • INVISIBLE:View不可见,但依旧占用空间,会正常参与measure和layout流程,只是不执行draw流程。
  • GONE:View不可见且不占用空间,不会参与measure和layout流程,系统会跳过该View的测量和布局,完全不占用绘制资源。

3. ScrollView嵌套ListView/RecyclerView为什么会出现测量问题?根本原因是什么?

  • 嵌套后会出现列表只显示一行、高度计算错误、滑动冲突等问题。
  • 根本原因:ScrollView的measure模式为UNSPECIFIED,在测量子View时,会给ListView/RecyclerView传递无限高度的MeasureSpec。ListView/RecyclerView默认测量模式下,会计算所有item的高度,导致高度计算异常,同时失去复用机制,性能急剧下降。
  • 解决方案:使用 NestedScrollView 或自定义测量逻辑

4. 自定义View时,requestDisallowInterceptTouchEvent()与View的绘制流程是否有关联?

两者没有直接关联,但存在间接配合场景。

requestDisallowInterceptTouchEvent()是用于事件分发的方法,作用是禁止父View拦截触摸事件,保证子View能正常接收触摸事件。

间接关联:触摸滑动事件会触发View的invalidate()或requestLayout(),进而触发绘制流程。比如滑动控件时,通过该方法处理事件冲突,保证滑动流畅,同时触发界面重绘。

5. 简述View的forceLayout()标记的作用,它是如何影响measure流程的?

  • forceLayout()标记是View的一个内部标记位,用于标记View需要强制重新测量。
  • 作用机制:调用requestLayout()时,会给View添加forceLayout标记;在measure流程中,系统检测到该标记,会强制执行onMeasure()重新测量,即使View尺寸看似没有变化,也会重新计算宽高,保证测量结果准确。该标记在测量完成后会自动清除。

五、自定义View实战(综合考察)

1. 自定义ViewGroup时,必须重写哪两个方法?为什么?**

必须重写onMeasure()和onLayout()两个方法。

  • onMeasure():ViewGroup默认没有实现测量逻辑,需要重写该方法,遍历子View,生成MeasureSpec,完成子View测量,再确定自身宽高。
  • onLayout():ViewGroup默认是空实现,需要重写该方法,遍历子View,调用子View的layout()方法,确定每个子View在父容器中的位置。
    缺少任意一个方法,ViewGroup无法正常测量和摆放子View,界面会显示异常。

2. 自定义View实现圆形图片,在onDraw()中需要注意哪些绘制流程上的细节?**

  • 避免在onDraw()中创建Bitmap、Paint等对象,防止频繁GC。
  • 处理padding属性,绘制时减去padding值,保证内容不紧贴边框。
  • 使用clipPath()或Xfermode实现圆形裁剪,注意硬件加速兼容性。
  • 关闭硬件加速不兼容的API,或针对该View关闭硬件加速。
  • 优化过度绘制,避免多层重叠绘制。
  • 图片复用,防止内存泄漏,及时回收无用Bitmap。

3. 如何实现一个支持宽高自适应(wrap_content)的自定义View?

核心是重写onMeasure(),针对AT_MOST模式做特殊处理。

步骤:

  • 重写onMeasure()方法,获取父View传递的宽高MeasureSpec。
  • 解析MeasureSpec的模式和尺寸,分别处理EXACTLY、AT_MOST、UNSPECIFIED。
  • 当模式为AT_MOST(wrap_content)时,设置自定义的默认宽高(根据控件内容计算)。
  • 调用setMeasuredDimension(),传入计算后的宽高。
  • 处理padding属性,保证自适应效果准确。

4. 在自定义View中,如何正确处理padding和margin属性?**

  • padding处理:padding是View内部边距,在onMeasure()计算宽高、onDraw()绘制内容时,调用getPaddingLeft()、getPaddingTop()、getPaddingRight()、getPaddingBottom()获取边距值,在绘制和测量时减去对应边距,保证内容不紧贴边框
  • margin处理:margin是View外部边距,属于ViewGroup的布局参数,自定义ViewGroup时,在onMeasure()和onLayout()中,通过LayoutParams获取margin值,测量子View时纳入计算,布局时预留margin空间,普通View无法处理margin。

5. 当View需要根据内容动态改变大小时,如何正确调用requestLayout()和invalidate()?**

  • View内容改变导致尺寸、位置变化时,先调用requestLayout(),触发measure和layout流程,重新计算宽高和位置;再调用invalidate(),触发draw流程,重绘界面。
  • 如果仅内容改变,尺寸位置不变,只需调用invalidate()即可,无需调用requestLayout(),减少不必要的测量布局,提升性能。

todo:surfaceview canvas画布

相关推荐
酉鬼女又兒3 小时前
零基础快速入门前端CSS Transform 与动画核心知识点及蓝桥杯 Web 应用开发考点解析(可用于备赛蓝桥杯Web应用开发)
开发语言·前端·css·职场和发展·蓝桥杯·html
前端Hardy3 小时前
Qwik 2.0 Beta 来了:不靠 AI,只靠 Resumability,首屏交互快到离谱
前端·javascript·面试
jjinl4 小时前
Android 资源说明
android
寂静or沉默4 小时前
Java程序员技术面试:如何清晰描述项目难点?逻辑模板!Java的原因与解决方案最新发布!
java·开发语言·面试
庞轩px4 小时前
模拟面试回答第十四问:双亲委派模型
jvm·面试·职场和发展·tomcat·类加载·类加载器·双亲委派模型
Mr_Xuhhh5 小时前
LeetCode 热题 100 刷题笔记:数组与排列的经典解法(续)
算法·leetcode·职场和发展
小雷君5 小时前
SpringBoot 接口开发5个高频踩坑总结
java·spring boot·后端·面试
打瞌睡的朱尤6 小时前
3.25蓝桥杯训练
职场和发展·蓝桥杯
AI成长日志6 小时前
【笔面试算法学习专栏】堆与优先队列专题:数组中的第K个最大元素与前K个高频元素
学习·算法·面试