news 2026/9/10 6:37:49

从UIView到ViewGroup:iOS转Android的心智模型重装指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从UIView到ViewGroup:iOS转Android的心智模型重装指南

从UIView到ViewGroup:一次心智模型的重装

先说一句可能得罪人的话:iOS开发者转Android,真正卡住你的往往不是语言,不是IDE,更不是那套乱七八糟的包管理,而是你脑子里那套关于“视图”的心智模型。

我在iOS上写了六七年UI,自认为对UIKit的布局、渲染、命中测试都摸得门儿清。转Android之后,前两周几乎天天在怀疑人生:为什么一个FrameLayout叠来叠去总是不听使唤?为什么我在XML里写了个wrap_content,运行起来却跟我想象的完全不一样?为什么别人老说要“性能优化”,我明明没写任何复杂的绘制代码?

后来我才意识到,问题的根源在于我在用UIView的思维去写ViewGroup的代码。这两个东西看起来都是“屏幕上的一块矩形区域”,但它们的职责边界、生命周期、布局机制、测量流程,几乎是两套完全不同的哲学体系。这篇文章不打算给你罗列“ViewGroup有哪些子类”这种烂大街的API清单,而是想聊聊我在这次迁移过程中,真正觉得值得写下来的那些“跃迁点”——尤其是从UIView的朴素的frame思维,跨到ViewGroup的measure/layout/draw三层协作机制时,那些必须重建认知的地方。

无论你是刚准备转平台的新手,还是已经被Android的布局折磨得够呛的iOS老兵,希望这篇东西能帮你少走一些我走过的弯路。

1. “UIView什么都会”与“ViewGroup各司其职”:第一波认知冲击

1.1 把UIView当成瑞士军刀的旧习惯

在iOS的世界里,UIView是一个非常“全能”的角色。它既是视图的载体,也负责处理触摸事件,还可以通过layer直接操作底层渲染,甚至你可以在一个UIView里随手addSubview,然后通过autoresizingMask或者Auto Layout来安排子视图的位置。简单说,UIView既是“一个控件”,也是“一个容器”,这两件事在UIKit里没有刻意区分。

正因如此,iOS开发者养成了一种习惯:遇到任何界面需求,第一反应是——“我能不能自定义一个UIView,然后在draw(_:)里面画出来,或者在上面叠子视图?”

这个习惯在iOS上没有任何问题,UIView对这些事情大包大揽,也不会出什么岔子。但到了Android,这套思路会立刻撞上一堵墙:因为Android把“视图”和“容器”这两种角色拆开了——View是那个被绘制、被布局的个体,而ViewGroup才是那个负责“测量并安排子View”的容器。你几乎找不到一个“既能当控件又能随意装子View”的全能存在。

这听起来像是API设计的差异,但它背后反映的是Android整个界面架构的一个核心思路:每一层只干一件事,并且把这件事干到极致。

1.2 ViewGroup不是“能装子View的View”这么简单

很多教程告诉你:“ViewGroup就是能包含其他View的View。”这句话没有错,但它严重低估了ViewGroup的分量。

在Android里,ViewGroup是一个抽象类,它真正做的事情有两件:

  • 定义布局参数(LayoutParams):每一个子View在被放进ViewGroup时,都必须携带一套符合父容器规则的LayoutParams,这套参数决定了子View将来在父容器里以什么尺寸和位置存在。
  • 递归驱动整棵视图树的测量与布局:ViewGroup的onMeasure()onLayout()两个方法,是整个Android UI系统的“引擎”。父容器告诉子View“你最多能有多大”(MeasureSpec),子View回答“我想要多大”,父容器再根据所有子View的诉求综合决策,最终在onLayout()阶段把所有View安放到各自的位置。

你可以把ViewGroup理解为“带管理制度的小区”:每栋楼(子View)可以有自己的高度和宽度诉求,但能不能盖、盖多高、挨着谁,最终要看小区的整体规划(父容器的onMeasureonLayout)。而UIView更像“一块可以自由粘贴的画布”,它虽然也有subviews的概念,但父视图对子视图的“管控”力度远没有ViewGroup这么强。

这个差异直接导致了一个结果:在iOS里,你设置一个view的frame,这件事基本就结束了;在Android里,你设置LayoutParams,只是给父容器提交了一份“诉求书”,最终结果还取决于父容器的测量规则。

下面这个表格可以帮你直观感受一下二者的区别:

维度UIViewViewGroup
定位既是被绘制的控件,也是可容纳子视图的容器纯粹的容器,负责测量和安排子View
子视图布局通过Auto Layout、Autoresizing或直接设置frame通过LayoutParams + onMeasure/onLayout
尺寸决定权子视图自己的frame说了算父容器根据MeasureSpec和子View诉求共同决定
坐标系bounds + center 相对简单受padding、margin、gravity等多种因素共同影响
自定义方式直接子类化UIView,重写draw或layoutSubviews需继承ViewGroup并实现onMeasure、onLayout,或直接使用现成容器
渲染模型主要依赖Core Animation的layer合成通过View.onDraw走Skia绘制,层级由Z序决定

我遇到过不少从iOS转过来的朋友,在Android里“new一个View,然后addView”,结果发现View没有出现在预期位置,甚至根本没有宽高——因为默认情况下一个View对象的宽高是0,你必须显式指定LayoutParams,并确保父容器会“听取”你的LayoutParams诉求。

1.3 一个典型的“用iOS思维写Android”翻车案例

举个我印象特别深的例子。刚开始转Android时,我需要在屏幕底部做一个类似UITabBar的自定义控件,上面有几个图标和文字,点击切换页面。在iOS里,我可能就是创建一个UIView,然后在里面addSubview几个UIImageView + UILabel,用Auto Layout或者frame把它们排好,完事。

到了Android,我下意识地继承了一个View(不是ViewGroup),然后在onDraw()里用Canvas把图标和文字画出来。画出来之后发现,点击区域的命中测试要自己写,触摸事件的分发要自己处理,尺寸的wrap_content表现也怪怪的……

后来一位Android老同事看了一眼代码,问:“你为什么不直接用一个LinearLayout,或者写个FrameLayout里面放几个ImageView和TextView?为什么要绕那么一大圈?”

我当时的回答是:“因为我想做一个自定义控件。”

他摇摇头说:“你这不是自定义控件,你这是跟自己过不去。Android的设计理念是组合优于自定义绘制。能用现成的View装起来,就绝不要自己去画。你如果非要在onDraw里画一个图标和文字,那等于放弃了Android系统帮你做好的所有触摸、点击、无障碍、状态恢复机制。”

这句话点醒了我。iOS开发者遇到自定义UI时,思维是“我去画一个”;Android开发者的第一反应则是“我能不能用几个现成控件拼出来”。这不是谁优谁劣的问题,而是两种架构理念的差异:UIKit把渲染和交互的灵活度下放给了UIView,而Android更倾向于让你在ViewGroup这个层级通过“组合”来构建界面,把真正的灵活度留给那些不得不自定义绘制的极端场景。

2. measure/layout/draw:必须重装的底层认知

2.1 系统会主动“问”每个View想要多大,而不是听你“告诉”它

这是我转Android之后最不适应的一点,也是我觉得最值得展开讲的一点。

在iOS里,你要设置一个view的大小,直接给view.frame = CGRect(x:y:width:height:)就完事。Auto Layout本质上也是你通过约束“告诉”系统这个view应该多大、在哪里,系统照做。

在Android里,事情变成了这样:

  1. 系统从根View(DecorView)开始,自上而下发起一次测量(measure)流程。
  2. 父View根据自身的MeasureSpec(一个包含模式和size的包装类),为每个子View计算出子View的MeasureSpec。
  3. 子View在自己的onMeasure()里根据这个MeasureSpec,结合自己内容的需求,计算出自己想要的大小,并调用setMeasuredDimension()保存结果。
  4. 测完之后,父View再进入布局(layout)阶段,根据测量结果把所有子View放到最终位置。
  5. 最后才是绘制(draw)阶段,逐个View执行onDraw()

也就是说,在Android里,系统的测量流程是“自顶向下层层询问”的模型——每个View都被问到“你能用多大空间?你最小需要多大空间?”,而iOS更像是“自底向上明确指定”的模型——子视图告诉你“我放在哪”,你不干涉。

这两个模型没有绝对的好坏,但它们确实决定了完全不同的编程思维。

经常有iOS转Android的人问我:“为什么我在iOS里设置一个固定大小的视图那么简单,在Android里却要纠结wrap_content、match_parent还有各种MeasureSpec?”

我的回答是:因为在Android的世界里,“大小”永远不是一个绝对值,而是一个协商结果。

2.2 MeasureSpec三种模式:UNSPECIFIED、EXACTLY、AT_MOST

MeasureSpec是Android测量机制中一个非常关键的概念,它由两部分组成:模式和尺寸。你可以把它理解成一个“带规矩的尺子”。

  • EXACTLY(精确模式):父View明确告诉子View,你就这么大,别讨价还价。当你给一个View设置match_parent或者一个具体的dp尺寸时,通常会走到这种模式。
  • AT_MOST(最大模式):父View告诉子View,你最多这么大,但如果你内容不需要那么多,可以小一点。wrap_content通常对应这种模式。
  • UNSPECIFIED(未指定模式):父View不限制子View,你爱多大就多大。这种情况一般出现在ScrollView等滚动容器里,或者系统内部测量的时候。

看到这里,iOS开发者可能会觉得熟悉:AT_MOST难道不是类似intrinsicContentSize加上约束上限吗?有点那个意思,但Android把这个机制在系统层面强制化了——几乎所有布局流程都基于这套协商逻辑,而不是“你设置了多少就是多少”。

具体到自定义View,重写onMeasure几乎是必须的。如果你不重写,默认实现会直接使用MeasureSpec的尺寸,这会导致wrap_content变成“填满父容器”的诡异效果——这是新手最容易踩的坑之一。

2.3 onLayout和onDraw之间的职责划分,比你想的更重要

测量完成后,进入布局阶段。在ViewGroup中,你必须实现onLayout(boolean changed, int l, int t, int r, int b),在这个方法里,你要做的就是遍历所有子View,调用child.layout(l, t, r, b)为它们设置最终的位置和尺寸。

一个很容易被忽略的点是:onLayout不仅决定了子View的位置,还会影响后续的绘制顺序和触摸事件分发区域。

绘制阶段的事情则归onDraw管。对于ViewGroup本身,通常情况下你不需要重写onDraw(因为容器的职责是“装”,而不是“画”),但如果你用一个自定义ViewGroup做背景绘制,也可以重写,只是要注意dispatchDrawonDraw的调用时机,避免背景被子View盖住的困惑。

我在实际开发中见过一个反例:有人把整个界面的背景图放在ViewGroup的onDraw里画,结果发现某些情况下子View居然盖不住背景,或者滚动时背景出现闪烁。原因就在于没有理解onDraw和dispatchDraw的区别——onDraw画的是ViewGroup自己,dispatchDraw才负责分发并绘制子View。如果你想在子View之上再画一层“浮层”,你需要重写的是dispatchDraw,在super.dispatchDraw之后继续用Canvas绘制覆盖物。

这整个认知链条,对我来说是一次“重装系统”级别的调整。iOS里我很少去纠结“系统什么时候问我要尺寸”“我的绘制和子视图绘制谁先谁后”这些事,但在Android里,这些细节就是每天的日常。

3. 布局哲学的分岔路口:Auto Layout的“约束” vs ViewGroup的“嵌套”

3.1 为什么Android开发者这么爱嵌套,而iOS开发者不觉得有必要

如果你刚接触Android,看一些复杂界面的XML布局文件,可能会被吓到:一个LinearLayout套着一个FrameLayout,里面又是一个RelativeLayout,再里面又有一个LinearLayout……五层六层嵌套很常见。

而iOS开发者通常会想:“这不是有Auto Layout吗?加几个constraint不就完了,为什么要套这么深?”

这里面的原因挺微妙的。Auto Layout的哲学是用约束描述视图间的关系——A的左边等于B的右边加8,C的宽度等于A的宽度的一半,所有约束组成一个线性方程组,系统解方程来布局。而Android传统的布局体系(LinearLayout、FrameLayout、RelativeLayout等)的哲学是用容器结构描述布局——你把东西放进什么样的容器里,容器自己有一套规则来摆布子View。

两种方式各有各的直观之处。约束关系适合表达“这个按钮始终贴着输入框下方”这类明确的相对关系;嵌套容器适合表达“这一块区域整体偏右、内部元素垂直排列”这类区块化的结构。

你不能简单地说谁更先进。但从iOS转过来的人,最痛苦的是需要重建“用嵌套表达布局”的直觉。在iOS里,如果你发现一个View的位置需要参照另一个View,你会加constraint;在Android里,你需要思考的是:能不能用一个父容器把这个View和它的参照物“包”在一起,然后通过父容器的gravity或者子View的layout_gravity来对齐?

我第一次从iOS转到Android时,在RelativeLayout里写了一堆layout_alignParentBottom、layout_toEndOf之类的属性,配着winphone一样的“配对”逻辑,直接看晕了。后来发现,用LinearLayout + gravity + layout_weight反而更直观。

3.2 用ConstraintLayout理解“约束”,是iOS开发者最舒服的过渡

好消息是,Android后来也引入了ConstraintLayout,它几乎是Android向Auto Layout思想靠拢的产物。如果你在iOS上对Auto Layout已经滚瓜烂熟,那么ConstraintLayout会是你的过渡利器。

ConstraintLayout的很多概念都和Auto Layout一一对应:你可以给View设置左右上下约束,可以设置链(chain)来等比分布,可以设置偏差比例(bias),甚至可以用Guideline(参考线)来模拟Auto Layout的margin和等宽约束。

我在实际工作中,几乎95%的页面都直接用ConstraintLayout打底。它既保留了我对“约束”的直觉,又不会像嵌套多层的LinearLayout那样制造深不见底的层级。

但这里有个需要警惕的坑:ConstraintLayout虽然性能优化得不错,但它依然不是万能的。有些场景下,嵌套容器反而更高效、更直观。比如一个简单的水平排列、垂直居中的情况,一行LinearLayout代码就搞定了,你用ConstraintLayout反而要写一堆constraintStart、constraintEnd、constraintTop、constraintBottom。写起来啰嗦,读起来也累。我的原则是:关系复杂到需要参照多个View的时候,用ConstraintLayout;简单的线性排列,直接用LinearLayout,不要为了“统一风格”而牺牲直观性。

3.3 一下子绕不开的坑:LayoutParams、margin和padding的生效时机

还有一个iOS开发者很困惑的点是:为什么我在Android里new一个View,addView进去之后,设置margin却没有任何效果?

这个问题的答案一句话就能说清:margin是写在LayoutParams里的,不是写在View上的。

在iOS里,你给UIView设置frame时,可以直接在外层再包一个容器来制造间距,或者用Auto Layout的constant。但在Android中,View本身没有“margin”概念,它的间距是通过父View的LayoutParams来控制的——也就是说,同一个View放进LinearLayout和放入FrameLayout时,margin的行为和生效方式是一样的(layout_gravity可能略有不同),但如果你想通过代码设置margin,必须先ViewGroup.MarginLayoutParams,再设layoutParams.setMargins(),最后setLayoutParams()

类似的还有padding,padding倒是View本身就是干这事,但结合不同容器时,padding的效果也要区分:父View设置了padding,子View的测量可用空间会相应缩小,这一点在自定义ViewGroup时特别容易出错。

我转Android后补的第一课,就是把“LayoutParams是父容器发给子View的‘工作许可’”这个概念刻在脑子里。它不是随便挂着好看的,它实际决定了子View在父容器里的尺寸和位置协商资格。搞明白这一点,你的Android布局才真正“开窍”。

4. 实战迁移路线图:从“会写”到“能架构”的四个阶段

很多iOS转Android的文章都在教你怎么看API、怎么写布局,但很少有人告诉你:你真正需要的是把整个“界面构建”的方法论重推一遍。这里面有一个我反复验证过的四阶段迁移路线,分享给大家参考。

4.1 第一阶段:破除“控件翻译”心态

刚转过去,你很容易试图在Android里寻找“UIView的等价物”——拿到一个界面需求,先想“这在iOS里是什么控件”,然后再去查“Android里对应的控件叫什么”。

这本身没有错,控件级映射表(UILabel -> TextView,UIImageView -> ImageView,UIButton -> Button)能帮你迅速上手。但你必须意识到,这种映射只能帮你写“简单页面”,一旦遇到复杂交互或自定义UI,这套对应关系就迅速失效了。

我自己就是在这个阶段翻过车——拿UIView的“全能思维”去套Android的View,结果写出了上面说的那个“自定义View画TabBar”的笑话。后来我给自己定了一个规矩:拿到一个UI需求,先问“我应该组合哪些现成组件”,而不是“我应该自定义什么”。这条规矩一直用到现在,帮我少踩了无数坑。

4.2 第二阶段:理解“管道”机制,而不仅仅是“布局算法”

布局算法(LinearLayout怎么摆、ConstraintLayout怎么约束)只是皮毛,真正区分iOS思维和Android思维的地方,在于对测量、布局、绘制三段流水线的理解。

  • iOS开发者的心智模型是:“视图设置好属性,系统帮我渲染。”
  • Android开发者的心智模型是:“系统发起测量,我响应;系统发起布局,我响应;系统发起绘制,我响应。每个环节我都可以介入。”

如果你只是调用一个setContentView(R.layout.main),那你确实“不需要理解”这段管道是具体怎么走的。但只要你开始做以下事情中的任何一件——自定义一个View、做复杂的性能优化、处理多指触摸、解决布局不刷新的Bug——你就必须把一个“响应式”的心智模型装进脑子里。

我个人的经验是,找几个简单的控件(比如一个带圆角的Button),先去看它的源码:TextView如何计算文本高度、ImageView如何根据adjustViewBounds调整测量尺寸。看两三个源码之后,你对“管道”的理解会有一个质的提升,绝对比看十篇博客文档都有用。

4.3 第三阶段:把“继承”换成“组合”,把“子类化”换成“委托”

iOS开发者习惯通过继承来扩展UIView的行为:自定义一个UILabel的子类,重写drawText(in:),或者做一个UIButton的子类,在里面加个badge。

Android里你当然也可以继承,但你会发现,Android社区更推崇的则是组合扩展ViewGroup:不要子类化一个Button去加badge,而是用一个FrameLayout把Button和一个TextView叠起来;不要自定义一个复杂的TabBar,而是用BottomNavigationView+Fragment组合实现。

如果你需要做可复用的复杂组件,优先尝试ViewGroup的封装(自定义组合控件),而不是走View.onDraw自己画。这既是Android系统鼓励的方向,也是性能和可维护性的最佳实践。这一点在上文1.3里已经很明确了,我这里想再加一层:组合不只是“视觉上组合”,还包括“交互的组合”。在Android里,一个ViewGroup天然带触摸分发,它可以决定“这个触摸事件是给子View还是自己处理”,这是iOS里UIView不轻易暴露给开发者的能力。

4.4 第四阶段:熟悉Android的“协作式”布局体系并形成自己的架构直觉

说到底,从UIView到ViewGroup的迁移,其实是从“独裁式”布局模型到“协作式”布局模型的迁移。

  • iOS的Auto Layout,你设置的约束就是最终结果的表达式,系统负责计算。主动权更多在“布局的定义者”手里。
  • Android的measure/layout/draw,每个View都在这个流程里有发言权,父容器通过MeasureSpec限制,子View通过测量回应,最终大家一起得出一个结果。主动权分散在整个视图树的每个节点。

一旦你真正形成了这种“协作”的直觉,你再看Android的架构思路,很多东西都会豁然开朗:为什么onMeasure不加UNSPECIFIED会导致ScrollView里的内容被截断?为什么RecyclerView的缓存复用机制要建立在ViewHolder对ItemView的复用上?为什么在onLayout里做动画会导致奇怪的重绘问题?

这些问题背后,全都是这套协作式布局体系的影子。

我个人的建议是,在你开始做第一个复杂自定义ViewGroup之前,先花一个下午认真读一下ViewGroup的源码里measureChildWithMarginslayoutChildren的实现。读完你会明白,所谓“架构跃迁”,跳的不是API,而是这套“协作”的思维框架。

5. 几个能够让你少赔两周时间的实操建议

最后分享几个具体的实操建议,每一个背后都是我或身边的人用真金白银的时间换来的教训。

5.1 工具链先磨利:Android Studio的调试视图层级功能,请务必用起来

iOS开发者用Xcode的View Hierarchy调试器很熟练,到Android里请第一时间找到Android Studio的Layout Inspector。它不仅能展示当前界面的视图树,还能看到每个View的MeasureSpec、LayoutParams实际解析值、margin和padding的最终效果。

我最开始排查一个“UI显示位置偏了”的问题,在代码里翻来覆去看了半天,最后用Layout Inspector一看,原来是某个ImageView的src内容自带内边距,跟我外层设置padding叠加了。这种问题在iOS的调试器里一目了然,Android里同样有对应的工具,关键是很多新人不知道用,或者到不了位。

5.2 命名和资源组织:尽早建立R文件思维

iOS里有Assets.xcassets和系统图片命名约定,Android则有res/目录下的一大堆子目录。不要小看这个差异,它会影响你的整个开发节奏。

R.id.xxxR.layout.xxxR.drawable.xxx,都是编译期的资源索引。命名规范一旦混乱,后期找资源的时间会让你崩溃。iOS转Android的人尤其要注意:drawable和mipmap的区分、values目录下的dimens/colors/styles的归类,决定了一个团队能不能同时维护多个模块。这不是“长毛绒”的小事,这是在为团队协作打基础。

5.3 建立你的“双平台UI映射表”

接口文档永远有边界,最好的办法是建立一张自己的UI组件映射表,把iOS的控件和Android的控件对应起来,并注明它们的差异:

iOSAndroid关键差异
UILabelTextViewAndroid有maxLines/ellipsize,注意字体单位sp
UIImageViewImageViewscaleType vs contentMode,注意adjustViewBounds
UIButtonButton/MaterialButtondrawableTop/Bottom等属性在XML里直接配
UITableViewRecyclerViewRecyclerView的ViewHolder机制需要显式实现
UIScrollViewScrollView/NestedScrollView注意测量模式差异,内容过长要小心
UINavigationControllerFragment + Toolbar/NavHost导航栈的概念不同,Fragment生命周期管理要重新学
UIStackViewLinearLayout不要过度嵌套,优先ConstraintLayout

这张表我自己用了很久,每次做需求都顺手往里面加补充项。它能帮你快速从“iOS怎么做”切换到“Android怎么做”,但一定要明白,映射表是拐杖,不是终点。最终你还是得把Android的那套“管道”机制内化成自己的思维习惯。

5.4 最后一条:务必花时间看Android官方文档的“App架构指南”

这可能是最枯燥、但最值得的一条建议。Android官方对“App架构”有一套非常明确的建议:UI层用ViewModel+StateFlow,数据层用Repository,界面状态用不可变状态流驱动。

iOS的MVC/MVVM虽然没有强制约束,但在Android里,如果你不按照官方推荐的架构来,后续的bug排查、状态恢复、进程重建会非常痛苦。特别是Activity/Fragment的生命周期远比UIViewController复杂,处理不好很容易出现内存泄漏和空指针。

我的建议是转Android后的第一个项目,哪怕是个小Demo,也尽量遵循ViewModel + StateFlow + ViewBinding这套官方模板。建一个干净的基座,比后面再重构要省太多事。

我这里提到的很多细节,可能在某些深度教程里被当作“基础中的基础”一笔带过,但正是这些“基础”营造了整个Android视图体系的氛围。UIView到ViewGroup的迁移,本质上是一场心智模型的重装,没有什么捷径可走,但如果你能理解这套“协作式布局”的思维方式,再回头去看那些API和组件,你会发现它们突然变得合理了起来,而你接下来要做的,就是把这种合理性内化成自己的默认思维。希望这篇分享能给你的跃迁过程省下一点时间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 6:35:28

数学可视化工具选型指南:按场景挑工具,一张表看完

数学可视化工具选型指南:按场景挑工具,一张表看完 【免费下载链接】awesome-math A curated list of awesome mathematics resources 项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-math 公式和符号堆在一起时,抽象概念很…

作者头像 李华
网站建设 2026/9/10 6:34:25

Hot100数组题全攻略:双指针、前缀和与哈希表套路详解

数组算是我在力扣Hot 100这个题库里认真啃下来的第一个专题。刚开始真没当回事,觉得数组不就是for循环加下标访问,能难到哪里去?直到有一次面试,被一道“和为K的子数组”问得当场卡壳,我才意识到数组题型远没有想象中简…

作者头像 李华
网站建设 2026/9/10 6:34:02

购物商城APP源码解读:从Android Studio导入到答辩演示全流程

简介:面向毕业设计和大作业场景的Android购物商城APP完整源码,基于Android Studio开发,覆盖注册登录、修改密码、重置密码(邮箱验证)、商品详情加载、购物车、个人信息修改等功能模块,适合正在深入学习Andr…

作者头像 李华
网站建设 2026/9/10 6:33:20

CANN/GE性能剖析特性介绍

GE Profiling 特性介绍 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、Ten…

作者头像 李华
网站建设 2026/9/10 6:32:34

AI文本去AI味:humanizer五层改造法,让机器写作拥有真人感

上周帮朋友看一篇品牌推文,他拍着胸脯说“这版绝对看不出是 AI 写的,我还专门让人性化处理过”。我读完前两段就乐了:结构是标准的“痛点—方案—升华”三段式,每一段都用“在……的今天”开头,三个排比句举例&#xf…

作者头像 李华
网站建设 2026/9/10 6:30:06

AI编程助手Skills从入门到实战:告别重复提示词,封装可复用技能

那段时间我快被自己蠢哭了。明明给 AI 编程助手写了一大堆“规则”,每次开新会话都得把同样的话粘贴一遍,结果它该犯的错一个没少。直到我把目光转向“Skills”这个词,才意识到问题不在提示词长度,而在我一直在用最笨的方式跟 AI …

作者头像 李华