You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI Blazor安卓端搜索时UI冻结问题解决方案咨询

Android端.NET MAUI Blazor搜索UI冻结的解决方案

你的问题核心是实时输入触发的高频过滤+大量带超长Base64图片的组件渲染,在Android有限的UI线程资源下导致卡顿,Windows设备性能更强所以无明显感知。下面是针对性的优化方案:

1. 防抖处理,减少触发频率

oninput事件会在每输入一个字符(包括退格)就触发一次,直接导致频繁的过滤和渲染。添加防抖逻辑,延迟300ms左右再执行过滤,避免短时间内多次触发:

private string _searchInput;
private CancellationTokenSource _debounceCts;

private string SearchInput
{
    get => _searchInput;
    set
    {
        _searchInput = value;
        // 取消之前的延迟任务
        _debounceCts?.Cancel();
        // 创建新的延迟任务,300ms后更新界面
        _debounceCts = new CancellationTokenSource();
        _ = Task.Delay(300, _debounceCts.Token)
            .ContinueWith(async _ => await InvokeAsync(StateHasChanged), 
                          TaskScheduler.FromCurrentSynchronizationContext());
    }
}

输入框代码保持不变:

<input type="text" @oninput="@((e) => { SearchInput = e.Value.ToString();})" />

2. 缓存过滤结果,避免重复计算

把productsToShow从计算属性改成私有字段,只在防抖触发时更新过滤结果,而非每次渲染都重新计算:

private List<Product> _productsToShow;
private List<Product> productList; // 已从数据库加载的原始列表

protected override void OnInitialized()
{
    _productsToShow = productList;
    base.OnInitialized();
}

// 改写SearchInput的setter,在防抖后执行过滤
private string _searchInput;
private string SearchInput
{
    get => _searchInput;
    set
    {
        _searchInput = value;
        _debounceCts?.Cancel();
        _debounceCts = new CancellationTokenSource();
        _ = Task.Delay(300, _debounceCts.Token)
            .ContinueWith(async tokenTask =>
            {
                if (tokenTask.IsCanceled) return;
                
                var lowerSearch = _searchInput.ToLower();
                var filtered = string.IsNullOrWhiteSpace(_searchInput)
                    ? productList
                    : productList.Where(item => item.Model.ToLower().Contains(lowerSearch)).ToList();
                
                await InvokeAsync(() =>
                {
                    _productsToShow = filtered;
                    StateHasChanged();
                });
            }, TaskScheduler.FromCurrentSynchronizationContext());
    }
}

渲染部分改用缓存的结果:

<div>
    @foreach (Product item in _productsToShow)
    {
        <ProductListItem Product="@item" />
    }
</div>

3. 优化Base64图片的加载与渲染

超长Base64字符串的解析是Android端的性能瓶颈,每次渲染组件都重复解析会严重阻塞UI线程,可通过以下方式优化:

  • 预缓存图片资源:加载productList时提前把Base64转成ImageSource缓存,避免重复转换:
    public class Product
    {
        public string Model { get; set; }
        public string ImageBase64 { get; set; }
        // 缓存的图片资源
        public ImageSource CachedImage { get; set; }
    }
    
    // 加载列表时预转换
    productList = dbContext.Products.ToList();
    foreach (var product in productList)
    {
        if (!string.IsNullOrWhiteSpace(product.ImageBase64))
        {
            var imageBytes = Convert.FromBase64String(product.ImageBase64);
            product.CachedImage = ImageSource.FromStream(() => new MemoryStream(imageBytes));
        }
    }
    
    在ProductListItem组件中直接使用缓存的图片:
    <!-- ProductListItem.razor -->
    <img src="@Product.CachedImage" alt="@Product.Model" />
    
  • 使用虚拟滚动:用Blazor自带的Virtualize组件替代普通foreach,只渲染可视区域内的列表项,大幅减少同时渲染的组件数量:
    <Virtualize Items="_productsToShow" Context="item">
        <ProductListItem Product="@item" />
    </Virtualize>
    

4. 后台线程执行过滤操作

如果productList数据量很大,把过滤逻辑放到后台线程,避免占用UI线程:

// 在防抖任务中改用Task.Run执行后台过滤
_ = Task.Run(() =>
{
    if (string.IsNullOrWhiteSpace(_searchInput))
        return productList;
    
    var lowerSearch = _searchInput.ToLower();
    return productList.Where(item => item.Model.ToLower().Contains(lowerSearch)).ToList();
}, _debounceCts.Token)
.ContinueWith(async task =>
{
    if (task.IsCanceled || task.IsFaulted) return;
    
    await InvokeAsync(() =>
    {
        _productsToShow = task.Result;
        StateHasChanged();
    });
}, TaskScheduler.FromCurrentSynchronizationContext());

最优组合方案

优先搭配防抖+虚拟滚动+图片预缓存,这三个方案能从触发频率、渲染数量、资源解析三个核心点解决Android端的UI冻结问题。

内容的提问来源于stack exchange,提问作者gbrbabos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:34:55