自定义ListViewAdapter更新异常:添加新数据不生效求助
问题分析与解决方案
首先咱们抓核心问题:Android里所有和UI相关的操作(包括通知Adapter数据变更)都必须在主线程(UI线程)执行,你当前的NotifyDataSetChanged()是在Hub的后台回调线程里调用的,这就是正常运行时不生效的根本原因——主线程根本没收到数据变更的通知,慢调试时只是线程调度偶然触发了更新,完全不可靠。
接下来一步步解决:
1. 把数据更新与通知移到UI线程执行
你的ReportsRecieved回调是后台线程触发的,必须把更新操作包裹在RunOnUiThread里,有两种实现方式:
方案一:修改回调代码
直接把整个更新逻辑放到UI线程块里:
_reportsHubConnector.ReportsRecieved += (tmpReports) => { this.RunOnUiThread(() => { adapter.updateReportsList(tmpReports); criticalButton.SetBackgroundColor(Android.Graphics.Color.Red); }); };
方案二:修改updateReportsList方法
让方法内部自动切换到UI线程,这样调用方不用额外操心:
public void updateReportsList(List<MobileReport> newlist) { if (context is Activity activity) { activity.RunOnUiThread(() => { // 添加新数据到当前列表 reports.AddRange(newlist); // 关键:如果Adapter支持过滤,必须同步更新原始数据集合,否则过滤时新数据会丢失 if (originalData == null) { originalData = new List<IMobileReport>(reports); } else { originalData.AddRange(newlist); } // 正式通知Adapter数据变更 NotifyDataSetChanged(); }); } }
2. 修复Adapter构造函数的originalData初始化问题
你实现了IFilterable接口,但构造函数里完全没初始化originalData,这不仅会导致过滤功能失效,新添加的数据在过滤时也会找不到。赶紧补上初始化:
public ReportsListViewAdapter(Context context, IEnumerable<IMobileReport> reports) { this.reports = reports.OrderBy(report => report.StudyDate).ToList(); this.context = context; // 初始化原始数据集合,用于过滤操作的基准数据 originalData = new List<IMobileReport>(this.reports); Filter = new ReportsFilter(this); }
3. 修正GetView里的UI赋值小bug
顺便提个细节错误,你在GetView里把Critical的值错赋给了txtSource,会覆盖之前的Source文本:
var txtCritical = row.FindViewById<TextView>(Resource.Id.txtCritical); // 原来的错误代码:txtSource.Text = reports[position].Critical.ToString(); txtCritical.Text = reports[position].Critical.ToString(); // 改成这样才对
这个不影响数据更新,但会导致UI显示混乱,记得修正。
为什么慢调试时会生效?
慢调试时线程调度会被打乱,后台线程的操作可能偶然和主线程的UI刷新时机重合,才触发了GetView,但这是完全不可靠的偶然情况,必须严格遵循Android的UI线程规则才能保证稳定运行。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

