fix: OTA 弹窗进度条修复
1. 进度条宽度用 post{} 延迟设置,确保容器已布局(width>0)
2. 进度回调限频 200ms,避免主线程过载
3. 用 runOnUiThread 替代 launch(Main),更简单可靠
4. 各状态切换加日志
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -209,10 +209,13 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
/** 待下载的更新 URL */
|
||||
private var pendingUpdateUrl: String? = null
|
||||
/** 上次进度更新时间(限制频率,避免主线程过载) */
|
||||
private var lastProgressUpdate = 0L
|
||||
|
||||
/** 开始下载并安装 APK */
|
||||
private fun startDownloadAndInstall() {
|
||||
val url = pendingUpdateUrl ?: return
|
||||
Timber.d("OTA: 开始下载安装流程, url=%s", url)
|
||||
updateManager.isUpdating = true
|
||||
// 保持屏幕常亮
|
||||
screenController.turnOn()
|
||||
@@ -221,19 +224,23 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
activityScope.launch {
|
||||
val file = updateManager.downloadApk(url) { progress, bytes ->
|
||||
// 进度回调在 IO 线程,切回主线程更新 UI
|
||||
launch(kotlinx.coroutines.Dispatchers.Main) {
|
||||
updateDialog.updateProgress(progress, bytes)
|
||||
// 限制进度更新频率:最多每 200ms 更新一次 UI
|
||||
val now = System.currentTimeMillis()
|
||||
if (now - lastProgressUpdate >= 200 || progress >= 100) {
|
||||
lastProgressUpdate = now
|
||||
runOnUiThread {
|
||||
updateDialog.updateProgress(progress, bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 回到主线程处理结果
|
||||
kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.Main) {
|
||||
if (file != null) {
|
||||
// 下载成功 → 触发安装
|
||||
Timber.d("OTA: 下载完成,触发安装")
|
||||
updateManager.installApk(file)
|
||||
} else {
|
||||
// 下载失败 → 显示错误
|
||||
Timber.d("OTA: 下载失败")
|
||||
updateManager.isUpdating = false
|
||||
updateDialog.showError()
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import com.xiaoqu.watch.R
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* OTA 更新弹窗 View(全屏覆盖)
|
||||
@@ -59,18 +60,23 @@ class UpdateDialogView @JvmOverloads constructor(
|
||||
tvProgress.visibility = View.GONE
|
||||
btnAction.visibility = View.VISIBLE
|
||||
btnAction.text = "立即更新"
|
||||
Timber.d("OTA弹窗: 显示发现新版本")
|
||||
}
|
||||
|
||||
/** 显示"下载中"状态 */
|
||||
fun showDownloading() {
|
||||
visibility = View.VISIBLE
|
||||
tvIcon.text = "\ueb2c"
|
||||
tvTitle.text = "请勿关机!"
|
||||
tvDesc.visibility = View.VISIBLE
|
||||
tvDesc.text = "正在升级系统..."
|
||||
progressContainer.visibility = View.VISIBLE
|
||||
tvProgress.visibility = View.VISIBLE
|
||||
tvProgress.text = "0%"
|
||||
btnAction.visibility = View.GONE
|
||||
updateProgress(0)
|
||||
// 进度条初始归零
|
||||
setProgressPercent(0)
|
||||
Timber.d("OTA弹窗: 显示下载中")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,10 +86,7 @@ class UpdateDialogView @JvmOverloads constructor(
|
||||
*/
|
||||
fun updateProgress(percent: Int, downloadedBytes: Long = 0) {
|
||||
if (percent >= 0) {
|
||||
// 已知进度:显示百分比
|
||||
val params = progressBar.layoutParams
|
||||
params.width = (progressContainer.width * percent / 100).coerceAtLeast(0)
|
||||
progressBar.layoutParams = params
|
||||
setProgressPercent(percent)
|
||||
tvProgress.text = "${percent}%"
|
||||
} else {
|
||||
// 未知进度:显示已下载大小
|
||||
@@ -101,10 +104,26 @@ class UpdateDialogView @JvmOverloads constructor(
|
||||
tvProgress.visibility = View.GONE
|
||||
btnAction.visibility = View.VISIBLE
|
||||
btnAction.text = "重新下载"
|
||||
Timber.d("OTA弹窗: 显示错误 %s", message)
|
||||
}
|
||||
|
||||
/** 隐藏弹窗 */
|
||||
fun hide() {
|
||||
visibility = View.GONE
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置进度条百分比(用 post 确保在布局完成后设置宽度)
|
||||
*/
|
||||
private fun setProgressPercent(percent: Int) {
|
||||
progressContainer.post {
|
||||
val containerWidth = progressContainer.width
|
||||
if (containerWidth > 0) {
|
||||
val barWidth = containerWidth * percent / 100
|
||||
val params = progressBar.layoutParams
|
||||
params.width = barWidth
|
||||
progressBar.layoutParams = params
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user