跳至主要內容

提供反馈

guodongAndroid大约 3 分钟

提供反馈

假设你有一个需要上传图片的函数。当用户点击上传按钮时,会出现加载进度条或者 spinners,这表明应用程序正在运行某些操作而不是停止工作。这对好的用户体验是至关重要的,没人喜欢无响应的应用程序。但是为用户提供反馈在代码中如何实现呢?

思考一下下面的任务,你要上传图片但是必须等待应用程序上传完成:

fun uploadImage(image: Image) {
    showLoadingSpinner()
    // Do some work
    uploadService.upload(image)
    // Work’s done, hide the spinner
    hideLoadingSpinner()
}

从上面的代码中,可以了解到以下信息:

  • 首先显示一个进度条。
  • 接下来上传一张图片。
  • 最后,当上传完成后,隐藏进度条。

不幸的是,上面的代码并非如此简单,因为进度条是有动画的,并且必须有代码实现这个动画。showLoadingSpinner 必须包含以下代码:

fun showLoadingSpinner() {
    showSpinnerView()
    while(running) {
        rotateSpinnerImage()
        delay() 
    }
}

showSpinnerView 用于显示真正的 UI 组件,下面的 while 循环用于处理动画。但是这个函数什么时候返回呢?

uploadImage 函数中,假设执行完 showLoadingSpinner 函数后进度条动画仍在运行,接下来就可以开始上传图片了。但是查看前面的代码,这是不可能的事情。

如果进度条动画在运行,就意味着 showLoadingSpinner 函数还没有返回。只要 showLoadingSpinner 返回,进度条动画就会停止并且将会开始上传图片。出现这种情况是因为阻塞调用 showLoadingSpinner 函数。

阻塞调用

阻塞调用是一个仅在完成时返回的函数。在上面的示例中,因为 showLoadingSpinner 函数使主线程保存忙碌,所有导致无法上传图片。但是当它返回时(把 running 置为 false),进度条动画就会停止。

那么如何解决在上传图片时进度条又有动画呢?

简而言之,你需要额外的线程来执行长时间运行的任务。

主线程也成为 UI 线程,因为它负责渲染屏幕上的所有内容,而这应该是它唯一的任务。这意味着它应该处理进度条的动画而不是上传图片,因为上传图片与 UI 无关。如果主线程不能做上传图片任务,那么谁可以执行上传图片任务呢?很简单,你需要一个新的线程来执行长时间运行的任务。

现在的计算机比 20 年、15 年甚至 10 年前要先进得多。那时,如果尝试同时执行多项操作,而计算机只能有一个执行线程,因此它们会死机。但是技术是进步的,现在的应用程序支持一种称为多线程的机制。每个线程都可以处理一个任务,共同完成所需的任务,这就是多线程的魅力。