Обновление индикатора выполнения атомарно / сразу после обновления в AsyncTask

#java #android #android-asynctask

#java #Android #android-asynctask

Вопрос:

У меня есть AsycTask выполнение действий, таких как копирование или перемещение файлов в приложении, и я часто обновляю индикатор выполнения в диалоговом publishProgress() окне.

ПРОБЛЕМА

Код работает почти нормально, хотя, когда AsyncTask выполняет действия и обновляет индикатор выполнения (вызовы setProgress() onProgressUpdate() ), он обновляется не сразу, пока задача не будет завершена… тем не менее TextView , обновленное в том же месте обновляется.

Я попробовал обходной путь… для использования sleep(1) в AsyncTask потоке, чтобы разрешить выполнение основного потока (обновите индикатор выполнения :-)). Это сработало, и индикатор выполнения обновлялся по мере удаления файлов… но существует большая разница во времени выполнения следующим образом.

Перед добавлением sleep(1)


Общее количество удаленных файлов — 3804

Среднее затраченное время — 5s (в среднем 3 теста)

После добавления sleep(1)


Общее количество удаленных файлов — 3804

Среднее затраченное время — 1m 40s (в среднем 3 теста)

Как вы можете видеть sleep(1) , это привело к огромному изменению времени выполнения. Есть ли другой способ обойти это… Чтобы обновить индикатор выполнения атомарно, я действительно благодарен за любые предложения…вот код…

Примечание: я попытался удалить те же файлы с помощью другого загруженного приложения filemanager, которое показывает индикатор выполнения во время удаления, а время указано относительно теста, в котором я добавил 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   "%tt"   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;
}