ListView多选列表实战:CheckBox状态管理与全选联动详解

1. 项目概述与场景定位

1.1 这个Demo到底解决了什么问题

多选列表是移动端开发里绕不开的一个硬需求。无论是文件管理器里的批量删除、购物车勾选结算、消息列表的批量已读,还是任务清单里批量更改状态,底层交互模型都指向同一套东西:ListView(或RecyclerView)+ CheckBox + 全选 + 实时数量反馈。

我在实际项目里遇到过好几次这种情况:需求文档就一句话——“像微信那样可以勾选多个,上面显示选了几个”,但真正动手写的时候发现坑全在后面。最典型的是列表滚动后CheckBox状态错乱,还有全选按钮和三方状态到底怎么联动,以及item点击事件和CheckBox点击事件互相干扰。这套“ListView+CheckBox+全选+显示选择数量”的组合看起来简单,实际上是把状态管理、视图复用、事件分发、UI反馈这几个点全踩了一遍,非常适合拿来当独立Demo吃透。

标题没有提RecyclerView,用的是ListView,这个选型其实很有意思。ListView虽然“老”,但它对视图复用机制的暴露更直观,convertView参透原理后,迁到RecyclerView只是换个壳的事。本文就用Android原生的ListView来拆这套组合拳。

1.2 适合谁读,读完能拿到什么

  • 刚开始接触Android列表开发的初学者,看完能独立写出一个多选列表Demo,并且理解每一行代码为什么这么写。
  • 工作一两年的开发,想系统梳理列表复用、事件冲突、状态同步的底层逻辑,这篇能帮你补上你以前“照着博客抄”没想明白的部分。
  • 正在做类似功能遇到Bug的同行,可以直接跳到第4部分,排查实录里整理的都是真实操作中高频踩中的坑。

我个人的经验是:与其丢给你一堆能跑的代码,不如把“为什么这么做”讲透。所以这篇不是CV操作册,核心目标是让你看完能自己设计一套多选方案,而不是只会搬运。

2. 整体设计与实现思路拆解

2.1 为什么用Adapter适配器模式来承载选择状态

Android里列表的每一行都是动态生成的,系统不会为列表单独建一套状态存储,数据在哪里,界面就长什么样。所以多选状态不能存在CheckBox里,必须存在数据模型层。这是整个设计的核心逻辑:数据驱动界面。

很多新手犯的错就是直接在Adapter里维护一个Boolean数组或HashSet来记录选中状态,这种做法的好处是快,坏处是如果数据和Adapter生命周期不统一,很容易出现状态和列表不同步的诡异问题。我更推荐把选中状态直接放进Bean里,例如:

public class ItemBean { private String name; private boolean checked; // getter、setter省略 }

这么做最大的优点是:不管列表怎么刷新、Adapter怎么重建,只要数据源在,选中状态就不会丢。某次项目里需要从列表页跳到详情页,返回后保持之前的勾选状态,因为状态存在Bean里,天然就实现了。

2.2 状态管理方案三板斧

很多人写多选列表,第一反应是给CheckBox加监听,在监听里把数据改了。这个方案能跑,但不优雅,而且会有副作用——后面我会讲到,CheckBox在滚动复用时会连续触发监听,造成性能浪费甚至逻辑错乱。

更好的做法是把布局里的CheckBox当成“展示组件”,真正决定谁选中的是Bean的checked字段。用户点击时统一走一个入口方法来更新数据和界面,可以叫updateCheckedState()。这样监听、状态更新、UI刷新三个动作被解耦,你后面加“全选”“反选”“清空”功能时,只需要复用这一个入口,不会出现三条代码路径互相覆盖的情况。

选择状态的存储结构,我个人实践下来最顺手的是HashSet<Integer>,泛型存position。为什么不用ArrayList?因为HashSet的查找是O(1),判断isChecked时高频调用,性能差距在几百上千条数据时就体现出来了。如果你把Bean和Adapter绑定得比较牢,直接用Bean里的boolean checked字段也可以,看个人偏好。但这个Demo里我选择双轨并用,既在Bean里标记状态,又在外部维护一个HashSet用于快速判断和批量操作。

2.3 整体架构:界面、逻辑、数据三层分离

这个项目虽小,但该有的层次不能省:

  • 数据层:Bean模型,携带选中状态的原始数据。
  • 逻辑层:Adapter内部的选择操作、全选/取消逻辑、数量统计逻辑。
  • 界面层:MainActivity负责ListView和全选CheckBox、数量TextView的联动。

这种分法看起来很“重”,但真实项目里这算轻量了。分层最大的红利是:界面怎么改、数据怎么换,核心的点击逻辑不用动。后来我把这个Demo迁移到RecyclerView时,只换了Adapter的壳,Bean和Activity里几乎没动。

3. 核心细节解析与关键代码落地

3.1 布局文件的三个关键点

首先是item布局。这一块有几个细节直接决定后面的开发体验:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" android:padding="12dp"> <TextView android:id="@+id/tv_item_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="16sp" android:textColor="#333333" /> <CheckBox android:id="@+id/cb_item_check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:focusable="false" /> </LinearLayout>

这里有个关键操作:给CheckBox设置android:clickable="false"和android:focusable="false"。我踩过很深的坑,默认情况下CheckBox会抢占点击事件,导致item整行点击失效或者事件冲突。把这两个属性关掉,让事件统一交给item根布局处理,CheckBox纯展示,状态由代码控制。

主界面的布局就三个要素:顶部一条显示“已选择X项”的TextView,一个全选CheckBox,下面一个ListView。全选CheckBox的文本我用“全选”两个字就够了,不需要额外加“全不选”,因为CheckBox自带选中状态。

顶部UI在LinearLayout里垂直排列即可,外层用match_parent撑满,内部组件用wrap_content或weight控制比例。需要说明的是,这个Demo里全选CheckBox放在ListView外面(布局顶部),这样顶部区域不随列表滚动,用户体验更好。

3.2 Adapter写法:ViewHolder + 复用机制全解析

Adapter是ListView的灵魂。ListView的每一项在滚动出屏幕时不会被销毁,而是作为convertView被回收到新进入屏幕的位置。如果不做ViewHolder缓存,每次getView都要findViewById,列表一长就卡顿。

public class MultiSelectAdapter extends BaseAdapter { private List<ItemBean> dataList; private LayoutInflater inflater; public MultiSelectAdapter(Context context, List<ItemBean> dataList) { this.dataList = dataList; this.inflater = LayoutInflater.from(context); } @Override public int getCount() { return dataList == null ? 0 : dataList.size(); } @Override public Object getItem(int position) { return dataList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.item_multi_select, parent, false); holder = new ViewHolder(); holder.tvName = convertView.findViewById(R.id.tv_item_name); holder.cbCheck = convertView.findViewById(R.id.cb_item_check); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } final ItemBean bean = dataList.get(position); holder.tvName.setText(bean.getName()); // 核心:每次getView都把界面状态强制同步成数据状态 holder.cbCheck.setChecked(bean.isChecked()); return convertView; } static class ViewHolder { TextView tvName; CheckBox cbCheck; } }

最后那行setChecked(bean.isChecked())是整个Adapter里不能省的一行。因为ListView的复用机制,一个View可能上一秒显示第5项,下一秒就滚到第12项的位置,如果不强制刷新CheckBox状态,就会出现“勾选A却导致B被勾选”的灵异事件。

3.3 全选逻辑的五种边界情况

全选按钮的逻辑是这套Demo里细节最多的部分。很多人的第一版代码是单击全选CheckBox就遍历把所有Bean的checked设为true,其实不对。全选至少要处理五种状态,照着表格核对:

场景操作期望结果
初始空列表点全选全选无效(没有数据可选),全选CheckBox保持未选中
全不选点全选全部勾选,计数变为列表总长度
部分选中点全选全部勾选,计数变为列表总长度
全部选中点全选全部取消,计数清零
列表数据变化增删后全选按钮状态需重新计算,不能沿用旧状态

全选状态的计算逻辑我写成一个独立方法,遍历所有Bean后判断是否全部为true,这个方法两个地方会用:一是全选按钮的显示状态判断,二是批量操作后主动刷新:

private void refreshAllSelectState() { if (adapter.getCount() == 0) { cbSelectAll.setChecked(false); return; } boolean allChecked = true; for (int i = 0; i < adapter.getCount(); i++) { if (!adapter.getItem(i).isChecked()) { allChecked = false; break; } } cbSelectAll.setChecked(allChecked); }

注意空列表时直接置false,否则遍历逻辑会得出“全部选中”的错误结论(因为循环体一次都没执行)。这是很多人会忽略的边界条件。

3.4 选中数量实时刷新方案

数量统计我用了一个非常简单的方案——维护一个int selectedCount字段,在每次状态变更时递增或递减,然后调用updateCountView()。不用每次遍历统计,性能好,代码也直观:

public void updateCountView() { tvCount.setText("已选择 " + selectedCount + " 项"); }

这个方案依赖于所有状态变更都必须走统一入口。如果你在几个地方各自改Bean的checked字段,计数就会失准。我是这样约束的:凡是改变选中状态的行为,全部通过Adapter暴露的setItemChecked(position)或selectAll(boolean)接口完成,这两个接口内部同时负责改Bean、更新HashSet、更新计数器,最后通知Activity刷新UI。

这样Activity里的代码会非常干净,不需要关心谁改了什么状态,只需要在回调里接收新的计数并刷新即可。

3.5 完整Activity:事件绑定的正确姿势

Activity层是展示层,负责所有UI控件的组装和监听事件绑定:

public class MainActivity extends AppCompatActivity { private ListView listView; private CheckBox cbSelectAll; private TextView tvCount; private MultiSelectAdapter adapter; private List<ItemBean> dataList = new ArrayList<>(); private int selectedCount = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = findViewById(R.id.list_view); cbSelectAll = findViewById(R.id.cb_select_all); tvCount = findViewById(R.id.tv_count); initData(); adapter = new MultiSelectAdapter(this, dataList); listView.setAdapter(adapter); // item点击事件:整行点击,切换选中状态 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ItemBean bean = dataList.get(position); bean.setChecked(!bean.isChecked()); if (bean.isChecked()) { selectedCount++; } else { selectedCount--; } adapter.notifyDataSetChanged(); updateCountView(); refreshAllSelectState(); } }); // 全选按钮 cbSelectAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { selectAll(isChecked); } }); } private void selectAll(boolean isChecked) { for (ItemBean bean : dataList) { bean.setChecked(isChecked); } selectedCount = isChecked ? dataList.size() : 0; adapter.notifyDataSetChanged(); updateCountView(); } }

有几个细节需要重点解释。

第一个是用setOnItemClickListener而不是在getView里给CheckBox设OnClickListener。整行点击统一在Adapter外部监听,数据更新也在外部,这样逻辑清晰,不易出“双触发”问题。

第二个是**notifyDataSetChanged()的位置不能省**。你改完Bean里的checked值,Adapter不知道,UI不会刷新。忘了这行,点100次界面都没反应,这是最常见的低级错误。

第三个是全选按钮的setOnCheckedChangeListener和手动setChecked()会互相触发回调,容易进入死循环。解决方案是加一个isProgrammaticChange标志位,禁止程序主动赋值时走监听逻辑。这个坑在第4部分排查实录里会细讲。

4. 常见问题排查与实战避坑记录

4.1 CheckBox状态错乱的根源与对策

这是多选列表里最高频的Bug,症状是滚动后某些行的勾选状态和实际点击的不一致。根源就是我前面提到的ViewHolder复用机制:一个View被反复使用,如果不强制重置状态,就会残留上一次的数据。

典型的错误写法是这样的:

// 这是错误示范 if (bean.isChecked()) { holder.cbCheck.setChecked(true); } // 没写else,等于“未选中的”那一分支什么都不做

这个写法就是Bug温床。因为复用的View可能之前是checked状态,滚动后显示给新数据,但新数据的isChecked()是false,你没重置,界面上显示的依然是true。所有的新数据行都默认显示的“已勾选”。

正确做法是无条件赋值,不存在“只有true才需要设置”的说法:

// 正确的做法 holder.cbCheck.setChecked(bean.isChecked());

这个坑我见过很多同行踩,包括我自己早期也犯过。从原理上彻底理解以后,就再也不会犯了。

4.2 notifyDataSetChanged和CheckBox监听器打架

另一类高频问题:在getView里给CheckBox绑定了OnCheckedChangeListener,而notifyDataSetChanged()刷新时会重新执行getView,这时候setChecked()会触发监听器,监听器里又修改了数据,再一次通知刷新,来回循环。轻则性能浪费,重则逻辑错乱,出现“点一个勾了三个”的怪象。

解决方案总结成一条原则:不要在getView里给CheckBox注册监听器,CheckBox的状态变更统一交给item点击事件处理。如果业务上有更复杂的场景,确实需要在CheckBox上单独监听,那可以用setOnClickListener(注意不是OnCheckedChangeListener),点击才触发,因为setChecked()并不会触发setOnClickListener,只有用户真实点击才会。

4.3 全选按钮的死循环与半选状态判断

全选CheckBox如果用setOnCheckedChangeListener监听,而代码里又要调用setChecked()来更新视图,就会触发回调,回调里又调用selectAll()方法,方法里又可能再setChecked()……形成了递归循环。

我这里采用的规避方案是引入布尔标志位:

private boolean isProgrammaticChange = false; cbSelectAll.setOnCheckedChangeListener((buttonView, isChecked) -> { if (isProgrammaticChange) { return; } selectAll(isChecked); }); // 需要程序更新全选状态时 isProgrammaticChange = true; cbSelectAll.setChecked(allChecked); isProgrammaticChange = false;

这个方案的思路是:区分“用户操作”和“程序刷新”。用户操作直接走逻辑,程序刷新时通过标志位拦截掉多余的递归触发。

另外还有一个常见细节:用户手动选中最后一个未选项时,全选CheckBox应该自动变成选中状态;用户取消某个已选项时,全选CheckBox应该自动取消。这一步就是refreshAllSelectState()方法的职责,在item点击和全选点击后都要调用一次。

4.4 数量显示和实际勾选不一致的排查思路

数量对不上,99%的情况是某个代码路径改了Bean的checked值,却没有更新selectedCount。比如你在Activity里直接写了bean.setChecked(true),绕过了计数器更新逻辑,结果界面勾选了,数量没变。

排查方法很直接:在selectedCount所有变更点打Log,输出当前的position和计数。如果发现某个点击事件后没有Log输出,说明那条路径根本就没走更新逻辑。我建议在项目里干脆定义一个统一的方法:

public void changeItemChecked(int position, boolean isChecked) { ItemBean bean = dataList.get(position); if (bean.isChecked() == isChecked) { return; } bean.setChecked(isChecked); selectedCount += isChecked ? 1 : -1; adapter.notifyDataSetChanged(); updateCountView(); refreshAllSelectState(); }

以后所有需要改变选中状态的地方,都只调这个方法。这样数量永远和真实勾选同步,排查问题也只需要看一个方法。

4.5 快速滑动的性能坑

数据量超过200条时,在getView里直接对CheckBox做复杂的drawable处理、或者在item里嵌套多层布局,都会导致快速滑动时帧率下降。实测下来有几个明显有效的优化:

  • 减少item布局层级,能用一个LinearLayout解决的不要用RelativeLayout嵌套。
  • CheckBox的button drawable尽量用轻量级的selector,不要用大尺寸图片。
  • 避免在getView里创建新对象(比如new一些临时类),复用一切能复用的对象。

配合ViewHolder +setTag缓存,200条数据快速滑动完全无压力,500条也能保持流畅。如果数据量到几千条,那就不建议继续用ListView了,应该果断切RecyclerView配合DiffUtil。

5. 功能扩展与迁移思路:从ListView到RecyclerView

5.1 给Demo增加“反选”和“清空”功能

这套结构扩展起来非常舒服。比如增加“反选”,只需要遍历一遍所有Bean,把每个checked取反,重新计算selectedCount,然后刷新:

btnInverse.setOnClickListener(v -> { for (ItemBean bean : dataList) { bean.setChecked(!bean.isChecked()); } selectedCount = dataList.size() - selectedCount; adapter.notifyDataSetChanged(); updateCountView(); refreshAllSelectState(); });

注意selectedCount = dataList.size() - selectedCount这个公式,反选后的数量就是总数减去之前的数量,这也是很多人容易写错的地方。

“清空”就是全不选,直接调用selectAll(false),逻辑完全复用。

5.2 迁移到RecyclerView时哪些能留、哪些要改

说实话,现在新项目里基本都是RecyclerView的天下了。但这个Demo的价值在于:核心逻辑,也就是数据模型承载状态、统一入口变更状态、全选/数量联动这三板斧,一套都不需要改。需要动的只有Adapter的壳:

  • getView变成了onCreateViewHolder+onBindViewHolder。
  • notifyDataSetChanged()换成notifyItemChanged(position)更好,只刷新变化的那一行。
  • item点击从setOnItemClickListener改为在ViewHolder里给根布局setOnClickListener。

状态管理方案和Activity里的事件联动逻辑,几乎原封不动。所以如果你正在用RecyclerView,也可以把第3部分的代码对照着改,整体思路完全通用。

5.3 真实项目里推荐的进一步加强

这个Demo是基础版,真实项目里通常还需要考虑:

  • 更多状态维度:除了选中/未选中,可能还要有“半选”状态(列表里部分子项被选中,父项显示半选)。Android原生的CheckBox不支持半选,需要自定义状态,一般用indeterminate属性模拟,或者自己做三态Drawable。
  • 批量操作:选中后底部弹出一个操作栏,显示删除、移动等按钮,这个直接在Activity里判断selectedCount即可,大于0就显示操作栏。
  • 性能监控:如果列表数据量大,建议用SparseBooleanArray代替HashSet做选中状态存储,它专为Android场景优化过,内存占用更小。
  • 数据异步加载:如果数据来自网络或数据库,每次刷新数据源后记得重新计算全选状态和数量,这个在onLoadFinished回调里调用refreshAllSelectState()和updateCountView()即可。

6. 写在最后的实操体会

这套ListView+CheckBox多选组合,我前后在不同项目里写过至少五遍,每一遍都会踩到新坑。最开始是状态错乱,后来是事件冲突,再后来是性能问题。但把所有问题都梳理清楚之后,我发现这类多选功能的套路非常固定:数据承载状态、统一入口变更、UI强制刷新。只要这三点到位,无论用什么列表控件都不会出大问题。

有一个小技巧想额外分享:如果你实际上线时发现CheckBox的默认样式和你App整体风格不搭,不要急着去换自定义Drawable,可以在布局里直接用android:button="@null"把默认勾选框隐藏,然后给item根布局设置一个Selector背景,用背景变化来表示选中状态。这样视觉上更统一,而且因为没有了真的CheckBox控件,事件冲突问题天然消失。

另外,做一个这样的功能Demo,我一般会顺手把“全选”按钮也做成一个TextView而不是CheckBox,点击时判断当前全选状态再决定下一步。有些设计稿里“全选”就是一个普通的文字按钮,做成CheckBox反而更难适配样式。判断全选与否仍然用refreshAllSelectState()的思想,只是UI从勾选框换成文字。这一点在对接UI设计师的时候尤其好用,他们经常在评审时临时改交互方案,代码结构只要够清晰,改起来就是几分钟的事。

如果你正在做的项目也需要类似功能,建议先拿这篇里的Demo骨架跑通一遍,再根据实际业务需求做功能扩展。遇到问题欢迎多交流,多选列表这套东西,值得花时间一次吃透。

相关新闻

不开窗口也能背单词:ToastFish 用 Windows 通知栏背单词使用指南

不开窗口也能背单词:ToastFish 用 Windows 通知栏背单词使用指南

不开窗口也能背单词&#xff1a;ToastFish 用 Windows 通知栏背单词使用指南 【免费下载链接】ToastFish 一个利用摸鱼时间背单词的软件。 项目地址: https://gitcode.com/GitHub_Trending/to/ToastFish 开会、上课、领导在场&#xff0c;背单词软件开着却没人敢点开。这…

2026/10/21 2:19:51 阅读更多 →
SatDump 卫星信号解码实战:15分钟出第一张气象云图

SatDump 卫星信号解码实战:15分钟出第一张气象云图

SatDump 卫星信号解码实战&#xff1a;15分钟出第一张气象云图 【免费下载链接】SatDump A generic satellite data processing software. 项目地址: https://gitcode.com/GitHub_Trending/sa/SatDump USB 线插上 RTL-SDR&#xff0c;天线怼到窗边&#xff0c;对着 137 …

2026/10/21 2:19:50 阅读更多 →
电池AI编程实战营系列之四:等效电路模型(ECM)仿真—从Thevenin到二阶RC,手写参数辨识

电池AI编程实战营系列之四:等效电路模型(ECM)仿真—从Thevenin到二阶RC,手写参数辨识

你学电池建模&#xff0c;是打算用 Simulink 还是纯 Python&#xff1f;【A】Simulink 生态成熟 &#x1f9ee; 【B】Python 更自由 &#x1f4a1; 【C】两个都学 &#x1f3af;本系列第04篇&#xff1a;手写电池等效电路模型(ECM)&#xff0c;从最常用的 Thevenin&#xff0…

2026/10/21 2:19:50 阅读更多 →

最新新闻

RAG效果差?问题多半出在知识库管理:清洗、分块与治理实战

RAG效果差?问题多半出在知识库管理:清洗、分块与治理实战

先说明一点&#xff1a;这个标题我深有同感。做了大半年RAG相关的东西&#xff0c;见过不少团队把精力全压在召回链路调参上&#xff0c;结果效果上不去&#xff0c;最后排查一圈&#xff0c;问题全出在知识库本身——脏数据、错分块、无版本、无评测&#xff0c;源头一乱&…

2026/10/21 3:06:07 阅读更多 →
基于MATLAB深度学习与LSTM的污水处理异常工况识别实践

基于MATLAB深度学习与LSTM的污水处理异常工况识别实践

简介&#xff1a;面向污水处理异常工况识别的MATLAB深度学习资料包&#xff0c;覆盖数据集、迁移学习网络结构、训练脚本到结果可视化全流程&#xff0c;适合环境工程与人工智能交叉领域的研究者、研究生及工程师&#xff0c;可用于异常工况建模、模型迁移与效果评估。包内共20…

2026/10/21 3:06:07 阅读更多 →
MiniMax 2.5 Function Calling 格式解析与 AI 编程工具落地实践

MiniMax 2.5 Function Calling 格式解析与 AI 编程工具落地实践

做IkunCoder这段时间&#xff0c;我最大的感受是&#xff1a;一个AI编程工具能不能真正“动手干活”&#xff0c;关键不在模型聊天多好&#xff0c;而在对function calling格式吃得透不透。最近一直在跟进MiniMax 2.5的function calling方案&#xff0c;研究它如何把“用户一句…

2026/10/21 3:06:06 阅读更多 →
火箭飞行仿真中推力曲线处理模块的设计与实践

火箭飞行仿真中推力曲线处理模块的设计与实践

1. 推力曲线为什么是仿真里最"磨人"的一块做火箭飞行仿真做过一段时间的朋友&#xff0c;应该都有一个共同感受&#xff1a;飞行力学方程、气动模型、控制律这些东西&#xff0c;理论上都有成熟套路可循&#xff0c;真正让人反复返工、调试到深夜的&#xff0c;往往是…

2026/10/21 3:06:06 阅读更多 →
Python+CNN卷积神经网络实战:土豆病害识别项目全流程解析

Python+CNN卷积神经网络实战:土豆病害识别项目全流程解析

1. 项目到底在做什么&#xff1a;别被“毕设”两个字吓住先说结论&#xff1a;基于 Python 和 CNN 卷积神经网络做土豆病害识别&#xff0c;本质上就是一个图像分类任务&#xff0c;核心目标是让程序拿到一张土豆叶子的照片&#xff0c;自动判断它属于哪种病害&#xff0c;比如…

2026/10/21 3:06:06 阅读更多 →
Nginx为何要用StatefulSet?稳定身份与持久化存储实战解析

Nginx为何要用StatefulSet?稳定身份与持久化存储实战解析

1. Nginx为什么会落到StatefulSet头上——先弄清楚值不值得先说个直觉判断&#xff1a;一听到“Nginx用StatefulSet部署”&#xff0c;大多数人第一反应是“写错了吧”。Nginx这种典型无状态的反向代理&#xff0c;常规做法就是Deployment挂ConfigMap&#xff0c;前面再套个Ser…

2026/10/21 3:05:06 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事&#xff1a;AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里&#xff0c;按宣传口径&#xff0c;本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”&#xff0c;而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起&#xff1a;用户到底在追求什么“封号重开”这四个字&#xff0c;放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流&#xff0c;背后是大量的时间和精力成本。正常情况下&#xff0c;没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”&#xff0c;而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时&#xff0c;就意识到&#xff1a;单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →