2

Я создал небольшое приложение, которое загружает файл с помощью диспетчера загрузки.
Все в порядке.
Я думал добавить небольшой Toast и показать пользователю текущий статус загрузки.
Так что я сделал что-то вроде следующего:Почему Тост не скрыт после окончания периода?

Thread t = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     int status = -1; 
     while ((status = checkDownloadStatus()) != -1 && status != DownloadManager.STATUS_FAILED && status != DownloadManager.STATUS_SUCCESSFUL) { 
        try { 
         Log.d("MyApp", "Sleeping for 500 while polling for status [ " + status + " ]"); 
         TimeUnit.MILLISECONDS.sleep(500); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
         Log.e("MyApp", e.getLocalizedMessage()); 
        } 
       } 
       Log.d("MyApp", "Stop sleeping!"); 
      } 
}); 
t.start(); 

Внутри checkDownloadStatus я показать Toast пользователю о состоянии загрузки: например, НАЧАТЬ/ОЖИДАНИЕ/ЗАВЕРШЕНА

Я вижу, что загрузка продолжается, и я вижу Toast во время загрузки и в журналах, которые я вижу:

Sleeping for 500 while polling for status [ 2 ] 
Sleeping for 500 while polling for status [ 2 ] 
Sleeping for 500 while polling for status [ 2 ] 
Sleeping for 500 while polling for status [ 2 ] 
….. 

Затем, когда загрузка будет завершена, я вижу в журнале :

Stop sleeping! 

Но Toast с последним сообщ по-прежнему отображается.

Что я делаю неправильно? Есть ли лучший способ добиться того, что мне нужно

UPDATE:

private int checkDownloadStatus() { 

     final Cursor c= dm.query(new DownloadManager.Query().setFilterById(downloadId)); 
     if (c == null) { 
      showUserStatus(getActivity().getString(R.string.download_not_found), Toast.LENGTH_LONG); 
     } 
     else { 
      c.moveToFirst(); 
      final int status = showStatusMessage(c); 
      c.close(); 
      return status; 
     } 
     return -1; 
    } 


private int showStatusMessage(Cursor c) { 
     String msg="???"; 
     int downloadStatus = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)); 
     switch (downloadStatus) { 
      case DownloadManager.STATUS_FAILED: 
       msg= getActivity().getString(R.string.download_failed); 
       break; 

      case DownloadManager.STATUS_PAUSED: 
       msg= getActivity().getString(R.string.download_paused); 
       break; 

      case DownloadManager.STATUS_PENDING: 
       msg= getActivity().getString(R.string.download_pending); 
       break; 

      case DownloadManager.STATUS_RUNNING: 
       msg= getActivity().getString(R.string.download_in_progress); 
       break; 

      case DownloadManager.STATUS_SUCCESSFUL: 
       msg= getActivity().getString(R.string.download_complete); 
       break; 

      default: 
       msg= getActivity().getString(R.string.download_is_nowhere_in_sight); 
       break; 
     } 
     showUserStatus(msg, Toast.LENGTH_LONG); 
     return downloadStatus; 
    } 


private void showUserStatus(final String msg, final int length) { 
     getActivity().runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       Toast.makeText(getActivity(), msg, length).show(); 
      } 
     }); 
    } 
+0

пост checkDownloadStatus() – Blackbelt

+0

@Blackbelt: Пожалуйста, смотрите обновления в OP – Jim

+0

I подумайте, что вам нужно попробовать «LENGTH_SHORT» вместо «LENGTH_LONG». –

ответ

1

Тост поставлен в очередь. Если вы вызываете showText с тем же текстом n раз, вы увидите тост с тем же текстом для n * length time. Сохраните ссылку на текущий Toast и вызовите Toast.cancel(), прежде чем показывать следующую.

E.g.

Toast mToast; 

private void showUserStatus(final String msg, final int length) { 
     getActivity().runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       if (mToast != null) { 
        mToast.cancel(); 
       } 
       mToast = Toast.makeText(getActivity(), msg, length); 
       mToast.show(); 
      } 
     }); 
    } 
+0

Это решило его, спасибо, но я не понимаю, как это поведению. Что вы подразумеваете под «Toast queued»? – Jim

+0

они буквально помещаются во внутреннюю очередь и показывают друг за другом. Отмена немедленно удалить текущий – Blackbelt

0

See, Вы звоните checkDownloadStatus() метод в состоянии в то время как петли, так что она будет называться снова и снова до тех пор пока условие не будет удовлетворять. вот почему тост снова и снова показывает. Тост покажет снова, прежде чем скрыть последнее показанное изображение, поэтому он выглядит как показ в течение долгого времени. (Извините за плохой английский)

+0

Условие удовлетворяет после завершения загрузки, поэтому я дохожу до Log.d («MyApp», «Stop sleep!»); '** вне ** цикла – Jim

1

Dont использовать в то время как петля для этого используйте таймер вместо

 Timer mtimer = new Timer(); 
     mtimer.schedule (new TimerTask() { 
      @Override 
      public void run() { 
       if((status = checkDownloadStatus()) != -1 && status != DownloadManager.STATUS_FAILED && status != DownloadManager.STATUS_SUCCESSFUL){ 
        try { 
         Log.d("MyApp", "Sleeping for 500 while polling for status [ " + status + " ]"); 
         TimeUnit.MILLISECONDS.sleep(500); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
         Log.e("MyApp", e.getLocalizedMessage()); 
        } 
       } 

      } 
     }, 0, 1000); 

Это будет работать после того, как раз в 1 сек

+0

И как это прекратится после того, как условие выполнено? – Jim

+0

mtimer.cancel(); –

+0

Внутри runnable? – Jim