Почему тост не скрывается после окончания периода времени?

Я создал небольшое приложение, которое загружает файл с помощью диспетчера загрузок.
Пока все в порядке.
Я подумал добавить маленькую 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 с последним сообщением все еще отображается.

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

ОБНОВЛЕНИЕ:

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();
            }
        });
    }

person Jim    schedule 22.04.2015    source источник
comment
после проверкиСтатус загрузки()   -  person Blackbelt    schedule 22.04.2015
comment
@Blackbelt: см. обновление в OP   -  person Jim    schedule 22.04.2015
comment
Я думаю, вам нужно попробовать «LENGTH_SHORT» вместо «LENGTH_LONG».   -  person Haresh Chhelana    schedule 22.04.2015
comment
@HareshChhelana: разница, насколько мне известно, составляет 1,5 секунды stackoverflow.com/questions/7965135/   -  person Jim    schedule 22.04.2015


Ответы (3)


Тосты стоят в очереди. Если вы вызовете showText с одним и тем же текстом n раз, вы увидите всплывающее уведомление с одним и тем же текстом в течение времени n * длины. Сохраните ссылку на текущий 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();
            }
        });
    }
person Blackbelt    schedule 22.04.2015
comment
Это решило это, спасибо, но я не понимаю поведение. Что вы имеете в виду под Toast are queued.? - person Jim; 22.04.2015
comment
они буквально ставятся во внутреннюю очередь и показываются один за другим. Отмена немедленно удалить текущий - person Blackbelt; 22.04.2015

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

        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 секунду

person Murtaza Khursheed Hussain    schedule 22.04.2015
comment
И как это перестает быть перепланировано после выполнения условия? - person Jim; 22.04.2015
comment
Конечно, когда ваше условие будет выполнено, отмените его. просто - person Murtaza Khursheed Hussain; 22.04.2015

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

person Rahul Sharma    schedule 22.04.2015
comment
Условие выполняется после завершения загрузки, поэтому я достигаю Log.d("MyApp", "Stop sleeping!"); вне цикла - person Jim; 22.04.2015