【问题标题】:Why is the Toast not hidden after the time period ended?为什么Toast在时间段结束后没有隐藏?
【发布时间】:2015-06-29 20:38:19
【问题描述】:

我创建了一个使用下载管理器下载文件的小应用程序。
到目前为止一切正常。
我想添加一个小的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();
            }
        });
    }

【问题讨论】:

  • 发布 checkDownloadStatus()
  • @Blackbelt:请参阅 OP 中的更新
  • 我认为你必须尝试“LENGTH_SHORT”而不是“LENGTH_LONG”。
  • @HareshChhelana:AFAIK 的差异是 1.5 秒 stackoverflow.com/questions/7965135/…

标签: java android multithreading android-download-manager android-toast


【解决方案1】:

你看,你在while循环条件中调用了checkDownloadStatus()方法,所以它会一次又一次地被调用,直到条件不满足。这就是吐司一次又一次出现的原因。 Toast 会在隐藏最后显示之前再次显示,所以看起来好像显示了很长时间。(抱歉英语不好)

【讨论】:

  • 下载完成后条件确实满足,这就是为什么我到达循环的Log.d("MyApp", "Stop sleeping!"); outside
【解决方案2】:

Toast 已排队。如果您用相同的文本调用 showText n 次,您将看到一个在 n * 长度时间内具有相同文本的 toast。保留对当前 Toast 的引用并在显示下一个之前调用 Toast.cancel()。

例如

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

【讨论】:

  • 这解决了谢谢,但我不清楚行为。 Toast are queued. 是什么意思?
  • 它们实际上是放在一个内部队列中并一个接一个地显示。取消立即删除当前的
【解决方案3】:

不要使用while循环,而是使用Timer

        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 秒后运行一次

【讨论】:

  • 而这个条件满足后如何停止重排?
  • offcourse,当你的条件满足时,取消它。简单
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 2014-09-30
  • 1970-01-01
相关资源
最近更新 更多