首页 > 解决方案 > 在 AsyncTask 中更新后自动/立即更新进度条

问题描述

我有一个AsycTask执行操作,例如在应用程序中复制或移动文件,并且我经常使用publishProgress().

问题

该代码几乎可以正常工作,尽管当AsyncTask执行操作并更新进度条(调用)setProgress()onProgressUpdate(),它不会立即更新,直到任务完成......但TextView在同一位置更新的内容会更新。

我尝试了一种解决方法...sleep(1)AsyncTask线程中使用以允许主线程执行(更新进度条:-))。这有效,并且随着文件被删除,进度条得到了更新......但是执行时间有很大差异,如下所示。

添加前 sleep(1)


删除的文件总数 -3804

平均花费时间 - 5s(平均 3 次测试)

添加后 sleep(1)


删除的文件总数 -3804

平均花费时间 - 1m 40s(平均 3 次测试)

如您所见,这sleep(1)导致了执行时间的巨大变化。有没有另一种方法来解决这个问题......为了使进度条自动更新 ,我非常感谢任何建议......这里是代码......

注意:我尝试使用另一个下载的文件管理器应用程序删除相同的文件,该应用程序在删除过程中显示一个进度条,并且时间与我添加 sleep(1) 的测试相关(1m 40s)


我的 doInBackground()

@Override
protected Boolean doInBackground(HashMap.SimpleImmutableEntry<Integer, File[]>... args) {
  mTask = args [0].getKey ();
  mFiles = args [0].getValue ();

// This calls the method according to task
   
  switch (mTask) {
  case TASK_COPY:
      return copy ();

  case TASK_MOVE:
      return move ();
  ...
  }
}

我的 onProgressUpdate()(我更新视图的地方,我打电话时经常调用它publishProgress()

@Override
protected void onProgressUpdate (Object[] values) {
    ...
                    
    // THIS IS WHERE I UPDATE VALUES OF PROGRESS BAR IN PERCENTAGE
    // instance fields
    // private AtomicLong mProgress, mLimit
    
    double i = mProgress.get (), j = mLimit.get ();
    int k = ((int) (j < 1 ? 0 : (i / j) * 100));

    // THIS mTextView updates properly immediately
    mTextView.setText (mTaskMsg + k + "%\t\t" + mProgress.get () + "/" + mLimit.get ());
    
    // but this progress bar does update until task is fully done (that is to 100) unless i sleep(1)
    mProgressBar.setProgress (k, true);
}

从 asynctask 线程调用的其他方法...

// implemented FileVisitor

@Override
public FileVisitResult visitFile (Path path, BasicFileAttributes attrs) {
    mProgress.incrementAndGet ();
    publishProgress ();
            
    // THIS IS WHERE I AM FORCED TO SLEEP TO ALLOW PROGRESS UPDATE IN MAIN THREAD
       
    try {
        Thread.sleep(1); // NOT REALLY THE BEST I KNOW...
        Files.delete (path); }
    catch (Throwable t) {
        publishProgress (ERROR_CODE, t); }
    return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed (Path path, IOException io) {
     mProgress.incrementAndGet ();
     publishProgress (ERROR_CODE, io);
     return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory (Path path, IOException io) {
     mProgress.incrementAndGet ();
     publishProgress ();

     try {
         Files.delete (path); }
     catch (Throwable t) {
         publishProgress (ERROR_CODE, t); }
    return FileVisitResult.CONTINUE;
}

...

private boolean delete () {
    publishProgress ();
    try {
        if (mFiles [0].isDirectory ()) {
            Stream<Path> s = Files.walk (mFiles [0].toPath ());
                    
        // I count the files here myself because the count method
        // of the stream crashes if files are 3000+ the app with no exception...i caught Throwable.
        // Though its not the issue...
            s.forEach (this);
            publishProgress ();

            Files.walkFileTree (mFiles [0].toPath (), this);
            }
            else {
                 mLimit.incrementAndGet ();
                 mProgress.incrementAndGet ();
                 publishProgress ();

                 return mFiles [0].delete ();
            }
     }
     catch (Throwable t) {
          publishProgress (ERROR_CODE, t); }
    return false;
}

标签: javaandroidandroid-asynctask

解决方案


推荐阅读