为啥在循环内调用 publishProgress 并多次调用(没有循环)会显示不同的行为?

Posted

技术标签:

【中文标题】为啥在循环内调用 publishProgress 并多次调用(没有循环)会显示不同的行为?【英文标题】:Why does calling publishProgress inside a loop, and calling it a number of times (without a loop), show different behavior?为什么在循环内调用 publishProgress 并多次调用(没有循环)会显示不同的行为? 【发布时间】:2015-11-15 09:21:51 【问题描述】:

我正在使用this library 通过AsyncTaskonProgressUpdate 方法在Activity 的UI 中显示ProgressBar。

所以我为此写了一个 SSCCE。 问题在于doInBackground() 内部,当我在循环迭代 100 次中调用 Thread.sleep(60) 并在每次迭代中调用 publishProgress(i) 时,我可以看到 DeterminateProgressBar 按顺序填充颜色(有点进行动画显示颜色),如下所示

@Override
    protected void onProgressUpdate(Integer... values) 
        progressBarDeterminate.setProgress(values[0]);
    

    @Override
    protected String doInBackground(Void... voidArgs) 
        ((MainActivity) context).runOnUiThread(new Runnable() 
            public void run() 
                Toast.makeText(context, "doInBackground of MyTask called", Toast.LENGTH_SHORT).show();
            
        );

        for(int i = 0; i <= 100; i++)
            try 
                //publishProgress(i);
                Thread.sleep(60);
             catch (InterruptedException e) 
                e.printStackTrace();
            
            publishProgress(i);
        

但是当我离开循环并调用Thread.sleep(60),然后是publishProgress(30),然后是Thread.sleep(60),然后是publishProgress(60),然后是Thread.sleep(60),然后是publishProgress(100),我看不到ProgressBar 依次进行,而是在doInBackground 结束时一步一步填充颜色。

@Override
    protected void onProgressUpdate(Integer... values) 
        progressBarDeterminate.setProgress(values[0]);
    

    @Override
    protected String doInBackground(Void... voidArgs) 
        ((MainActivity) context).runOnUiThread(new Runnable() 
            public void run() 
                Toast.makeText(context, "doInBackground of MyTask called", Toast.LENGTH_SHORT).show();
            
        );

        try 
            Thread.sleep(60);
         catch (InterruptedException e) 
            e.printStackTrace();
        
        publishProgress(30);

        try 
            Thread.sleep(60);
         catch (InterruptedException e) 
            e.printStackTrace();
        
        publishProgress(60);
        try 
            Thread.sleep(60);
         catch (InterruptedException e) 
            e.printStackTrace();
        
        publishProgress(100);
        return "doInBackground of MyTask returning.";
    

第二种方式更适合我的应用。所以问题是为什么!我该如何解决这个问题?

【问题讨论】:

onProgressUpdate尝试Log.d values[0],你看到了什么? 【参考方案1】:

setProgress(int); 方法不能顺利更新进度条。 如果你的最大值是100,当你设置进度为30时,它会直接显示进度填充到30%。

在您的第一个代码示例中,它看起来很流畅,因为您有 1 个非常 60 毫秒。

您应该添加更多步骤或使用真实的进度值(例如下载百分比)。

【讨论】:

以上是关于为啥在循环内调用 publishProgress 并多次调用(没有循环)会显示不同的行为?的主要内容,如果未能解决你的问题,请参考以下文章

方法 publishProgress 必须从工作线程调用,目前推断线程为主线程

shell:为啥循环内调用脚本,遇到exit会退出循环?

为啥 comb 在循环内的行为不同?

为啥 memset() 放在循环体内时不能正常工作?

为啥我们在冒泡排序算法的内循环中使用 `length-i-1`

在 GZIP 解压过程中设置 ProgressBar maxValue 和 publishProgress 值