在从 Internet 下载数据期间,在 AsyncTask 的 onProgressUpdate 中显示确定的 ProgressBar

Posted

技术标签:

【中文标题】在从 Internet 下载数据期间,在 AsyncTask 的 onProgressUpdate 中显示确定的 ProgressBar【英文标题】:Show determinate ProgressBar in onProgressUpdate of AsyncTask during the time taken to download data from the internet 【发布时间】:2015-11-13 22:32:12 【问题描述】:

我正在尝试使用 this library 在 AsyncTask 的 onProgressUpdate() 的活动屏幕上发布进度,该任务用于从 Internet 下载一些数据。他们提供的演示应用程序使用Handler 来演示这一点。我需要在 AsyncTask 中使用它。

以下代码 sn-p 来自他们演示应用程序中的代码。

我的问题是:

    onProgressUpdate 得到一个参数Progress... values,并且 根据documentation,它是“指示的值 进步。” 但是 我不明白这意味着什么,以及如何 使用这个论点。在我看到的例子中,他们正在做 类似:

    progressBar.setProgress(Integer.parseInt(values[0]));
    

    为什么他们只使用传递数组中的第一个值 (值[0])?

    AsyncTask 如何知道完成需要多长时间 下载操作。我想显示 ProgressBar 的进度 完成下载所用时间的值 0 到 100 手术。

    通过progressBarDeterminate.setVisibility(View.VISIBLE) in onPreExecute 和做 progressBarDeterminate.setVisibility(View.GONE)onPostExecute,我们确保它仅在数据出现时显示 正在下载,但我们如何确保它从 开始位置到最终位置 下载数据(当我们不知道它到底有多长时 去下载数据)?

来自演示示例的代码(它使用 Handler,但我需要在 AsyncTask 中执行此操作)

public class MainActivity extends AppCompatActivity 
    ProgressBarDeterminate progressBarDeterminate;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        progressBarDeterminate = (ProgressBarDeterminate) findViewById(R.id.progressDeterminate);

        progressTimer.start();
    


        Thread progressTimer = new Thread(new Runnable() 

                @Override
                public void run() 
                    for(int i = 0; i <= 100; i++)
                        try 
                            Thread.sleep(30);
                         catch (InterruptedException e) 
                            e.printStackTrace();
                        
                        handler.sendMessage(new Message());
                    
                
            );

            Handler handler = new Handler(new Handler.Callback() 
                int progress = 0;
                @Override
                public boolean handleMessage(Message msg) 
                    progressBarDeterminate.setProgress(progress++);
                    return false;
                
            );

【问题讨论】:

【参考方案1】:

在回答您的第一个问题时,onProgressUpdate() 采用 varargs 参数。这意味着它可以采用不定数量的指定类型的参数。例如:

public void someMethod(String... args) 
    //...

可以这样调用,someMethod("Hi!")someMethod("Hi", "there", "welcome", "to", "SO")

更多关于 varargs 的信息可以在 here 找到。这些参数的访问方式与访问数组的方式相同。如果那里只有一个参数,那么您可以使用args[0]

编辑: 关于您的第二个问题,android 开发人员javadocs 中提供了一个很好的示例:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> 
     protected Long doInBackground(URL... urls) 
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) 
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         
         return totalSize;
     

     protected void onProgressUpdate(Integer... progress) 
         setProgressPercent(progress[0]);
     

     protected void onPostExecute(Long result) 
         showDialog("Downloaded " + result + " bytes");
     
 

也就是说,答案实际上取决于您的情况。假设在上面的示例中您需要下载 10 个 URL。设置for 循环以按顺序下载每个URL,一旦URL 完成,就会调用publishProgress(),将当前值转换为百分比数字(i / (float) count) * 100)。希望这能回答您的问题!

【讨论】:

由于doInBackground 采用可变参数,您可以像对待数组一样对待urls(即URL[] 对象)。所以,它有一个长度和URL 成员。 在我的应用程序中,在doInBackground 中,数据来自 Web 服务,它的类型很复杂(类似于 JSON),然后我在从 doInBackground 返回之前解析它。所以我不知道如何找出 for 循环应该迭代的迭代次数(即count 变量)。你能推荐点什么吗? @Solace 恐怕不行,抱歉,我从未在 Android 中使用过 JSON 没问题,非常感谢您的回答。我要接受它。我想我要调用publishProgress 三次,在调用 web 服务之前,在数据到来之后,在它被解析之前,在它被解析之后。 @Solace 可以。还要记住,如果您的情况不适合使用百分比样式的更新栏,您可以从publishProgress() 返回任何您喜欢的内容,而不仅仅是Integer。它可以是 String 用于消息、图像资源值等。

以上是关于在从 Internet 下载数据期间,在 AsyncTask 的 onProgressUpdate 中显示确定的 ProgressBar的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch.Net.UnexpectedElasticsearchClientException:在从 ES 获取数据期间

在从 php 会话注销期间取消设置 cookie 有啥意义?

如何让 HSQLDB 在从 .script 文件初始化数据源期间发出错误消息?

在从 Google Play 在设备上安装期间,应用程序包是不是会转换为询问?

如何在从另一个小部件拖放事件期间突出显示表格单元格

如何在从模板创建 RStudio 项目期间运行 Shiny 应用程序?