ProgressDialog只会短暂显示。

3
编辑:这与ProgressDialog doesn't show just flashes不同。
我确保在网络通信和文件操作中使用AsyncTasks,并显示一个不定时、可取消的ProgressDialog,直到任务完成,因为我认为我应该这样做。
在某些情况下——比如慢速移动互联网连接、旧的低性能设备——这可能需要几秒钟。但是在其他情况或其他设备上,完全相同的任务可能会非常快速地完成,导致ProgressDialog仅在屏幕上闪烁一瞬间。
这里有最佳实践吗?我能想到几个选项:
1. 保持原样,知道一些用户会有那种闪烁的效果。 2. 强制ProgressDialog在消失之前保持可见的最短时间(半秒、一秒),即使任务已经完成——但我讨厌引入人工延迟的想法。 3. 计时任务,只有当任务花费的时间超过最小设置时间(如半秒钟)时才显示ProgressDialog。问题是这不是真正的解决方案;如果任务花费的时间少于这段时间,则很好;如果任务需要很长时间,则很好——但如果最小时间为0.5秒,而任务实际上需要0.7秒,则又会出现同样的问题……一个短暂的闪烁。 4. 如果您可以监视任务的进度,从前几分之一秒或前x个百分比进行简短的测试和估计,以确定完成任务需要多长时间;如果预计需要一段时间,则显示ProgressDialog。但这将非常复杂,并不是每个后台任务都适合这种进度估算。
哪种方式最好?我错过了什么选项吗?有没有一种方法可以设置ProgressDialog,使其仅在有明显延迟时才显示?(我怀疑有这种神奇的方法)。其中是否有一种“标准”解决方案?

3
没有标准的方法,你已经有了所有正确的想法。显示你的ProgressDialog,然后在一小段延迟之后(例如100毫秒)运行你的AsyncTask并不是一个糟糕的方法。你也可以只使用进度条(即旋转器),这是比对话框更小、更微妙的UI元素。 - CSmith
我同意CSmith的观点,我认为应该将其从对话框中移除,而是将其添加到用户界面的某个地方。这样它就不会让人感到突兀,但在需要时仍然可用。 - FoamyGuy
3个回答

2
强制ProgressDialog在消失之前保持可见,至少要有一定的时间(半秒、一秒),即使任务已经完成——但我讨厌引入人为延迟。
与让进度对话框在屏幕上短暂闪现相比,这是一个更好的解决方案。从用户的角度来看,它提供了一致性。如果有时出现,有时不出现,似乎就像某些东西没有正常工作。
我在我的异步任务中添加了一个long变量,在pre-execute中将其设置为System.nanoTime()。然后在post-execute中计算经过了多长时间,并将其与设置的最小时间进行比较。如果它低于该时间,则使用wait()等待剩余时间。目前,我将其设置为1.5秒的延迟,以确保有足够的时间读取进度对话框,然后才会消失。
private final class SyncPendingOrders extends AsyncTask<String, Integer, String> {

    long timer = 0;

    @Override
    protected void onPreExecute(){
        timer = System.nanoTime();

        pd = ProgressDialog.show(context,null,"Updating Pending Orders",true,false);
        pd.setIndeterminateDrawable(context.getResources().getDrawable(R.anim.spinner));
    }

    @Override
    protected String doInBackground(String... args) {

        updatePendingOrders();

        return null;
    }

    @Override
    protected void onPostExecute(String me){

        long clock = System.nanoTime()-timer - 2000000000;

        if(clock > 0)
        {
            try{
                wait(clock);
            }catch(Throwable e){

            }
        }

        PendingOrdersView();
        pd.dismiss();
    }

}

这样用户总是看到相同的框,并知道程序正在做什么。一致性是关键。


0
感谢CSmith的建议,我尝试将这个添加到我的AsyncTask中,以执行所有后台工作:
@Override
        protected void onCancelled() {
            completed = true;
            super.onCancelled();
            dismissProgressDialog(); //calls handler.post and dismisses dialog
        }

        @Override
        protected void onPostExecute(Void result) {
            completed = true;
            super.onPostExecute(result);
            dismissProgressDialog();
        }
@Override
        protected void onPreExecute() {
            super.onPreExecute();


            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException ie) {
                        return;
                    }
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (!completed) {
                                progressDialog = ProgressDialog.show(activity, activity.getString(R.string.loading_title), null, true, true, new DialogInterface.OnCancelListener() {
                                    @Override
                                    public void onCancel(DialogInterface dialog) {
                                        cancel(true);
                                    }
                                });
                            }
                        }
                    });

                }
            }).start();
        }

如果任务完成的时间少于指定的延迟时间(在本例中为500毫秒),则不会显示对话框。如果需要更长时间,则在延迟后显示。请注意,这并不能完全防止“闪烁”...例如,如果任务需要一秒钟,则对话框将闪烁半秒钟。

这似乎有所帮助,但我对解决方案并不完全满意,欢迎提出建议。


0

保持进度对话框不变,特别是对于网络操作,因为您可能在开发环境中有好运气,但也因为您无法控制您的互联网连接在真实情况下的速度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接