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

Flutter中加载数据前如何展示进度条?

自定义请求函数添加进度条实现方案

核心实现逻辑

  • 请求发起前触发进度条的启动状态
  • 大文件上传/下载等可感知进度的场景,通过原生XHR的progress事件或者Fetch API的ReadableStream监听已加载字节数,计算进度百分比实时更新
  • 普通接口请求无法获取真实进度的场景,可以用模拟进度逻辑:初始加载到70%-90%区间停止,请求成功后直接跳到100%后隐藏
  • 请求结束(无论成功/失败/超时/取消)都要触发进度条的完成/隐藏逻辑,避免进度条一直悬挂

原生XHR请求示例代码

// 进度条控制逻辑,可替换为你自己的UI组件实现
let progress = 0
const progressBar = {
  start: () => {
    progress = 0
    // 此处替换为你的进度条显示逻辑
    console.log('进度条开始显示')
  },
  update: (percent) => {
    progress = percent
    // 此处替换为你的进度条宽度/百分比更新逻辑
    console.log(`当前进度:${progress}%`)
  },
  finish: () => {
    progress = 100
    console.log('进度条加载完成,隐藏')
    // 加载完成后延迟重置进度,保证过渡动画正常展示
    setTimeout(() => {
      progress = 0
    }, 300)
  }
}

// 自定义XHR请求函数
function customRequest(options) {
  const xhr = new XMLHttpRequest()
  // 请求发起前启动进度条
  progressBar.start()

  // 监听下载进度(GET请求获取返回数据进度)
  xhr.addEventListener('progress', (event) => {
    if (event.lengthComputable) {
      const percent = Math.round((event.loaded / event.total) * 100)
      progressBar.update(percent)
    } else {
      // 无法获取总返回长度时用模拟进度
      const mockPercent = Math.min(progress + Math.random() * 10, 90)
      progressBar.update(mockPercent)
    }
  })

  // 监听上传进度(POST请求传文件/大数据场景)
  xhr.upload.addEventListener('progress', (event) => {
    if (event.lengthComputable) {
      const percent = Math.round((event.loaded / event.total) * 100)
      progressBar.update(percent)
    }
  })

  xhr.onload = function() {
    progressBar.finish()
    if (xhr.status >= 200 && xhr.status < 300) {
      options.success?.(JSON.parse(xhr.responseText))
    } else {
      options.error?.(xhr.statusText)
    }
  }

  xhr.onerror = function() {
    progressBar.finish()
    options.error?.('请求异常')
  }

  xhr.open(options.method || 'GET', options.url)
  xhr.send(options.data || null)
}

Fetch API 实现示例

async function fetchWithProgress(url, options = {}) {
  progressBar.start()
  const response = await fetch(url, options)
  const total = Number(response.headers.get('content-length'))
  const reader = response.body.getReader()
  let loaded = 0
  const chunks = []

  while (true) {
    const { done, value } = await reader.read()
    if (done) break
    chunks.push(value)
    loaded += value.length
    if (total) {
      const percent = Math.round((loaded / total) * 100)
      progressBar.update(percent)
    } else {
      const mockPercent = Math.min(progress + Math.random() * 8, 92)
      progressBar.update(mockPercent)
    }
  }

  progressBar.finish()
  // 拼接返回数据并解析
  const data = new Uint8Array(loaded)
  let offset = 0
  for (const chunk of chunks) {
    data.set(chunk, offset)
    offset += chunk.length
  }
  return JSON.parse(new TextDecoder().decode(data))
}

注意事项

  • 普通业务接口如果服务端没有返回content-length响应头,无法计算真实进度,使用模拟进度即可,用户感知差异很小
  • 进度条的动画过渡要做平滑处理,避免百分比跳变过于生硬
  • 所有请求结束的分支都要调用进度条完成方法,避免出现UI残留问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 07:45:04