【问题标题】:Progress dialog during tab switch选项卡切换期间的进度对话框
【发布时间】:2011-06-02 02:36:36
【问题描述】:

当用户从选项卡 A 切换到选项卡 B 时,需要很长时间(6 秒),所以我放置了一个进度对话框,让用户知道应用正在处理它。时间线如下:

  1. Activity B onCreate - 创建 ProgressDialog 并将长任务放在后台线程中。
  2. Activity B onStart
  3. 活动 B onResume
  4. 活动 B 出现在屏幕上

这一切都适用于一个“小”问题——应用程序间歇性地崩溃,因为 onResume 函数引用了由后台线程创建的东西。换句话说,这是一个经典的比赛条件。

为了修复竞争条件,我在 onResume 中的引用之前对线程进行了“加入”,但这使得进度对话框在后台线程完成之前不会显示(即它显示一瞬间,然后消失)并且应用程序的行为就像在后台线程工作时挂起一样。显然,在 onResume 完成之前,进度对话框无法显示。

我的问题是:如何在不使程序崩溃的情况下显示 ProgressDialog?还是我需要从 onResume 中获取违规引用,或者让应用挂起?

【问题讨论】:

  • 删除参考似乎是自然的解决方案。我还没有阅读onStartonResume 的详细信息,但我想它们应该运行得非常快,而不必等待另一个线程中的冗长计算完成。

标签: java android


【解决方案1】:

我最终使用了一个杂乱无章的解决方案,其中 onResume 函数等待它需要的中间结果,而不是等待整个后台线程完成。这很难看,我知道,但它似乎有效。

我认为,更好的长期解决方案是将所需对象的创建与创建时执行的冗长初始化步骤分开。时间线将是:

  1. 在创建时
  2. 创建对象
  3. 创建进度对话框
  4. 创建后台线程,让它对对象进行长时间初始化。
  5. onStart
  6. onResume(没有检查/睡眠循环)。

【讨论】:

    【解决方案2】:

    一个肮脏的解决方案是为第 1 步和第 2 步创建一个 ProgressDialog,然后为第 3 步和第 4 步创建第二个外观相同的对话框。

    【讨论】:

    • 这是否意味着在任何 onCreate/Start/Resume 函数中创建的进度对话框会在该函数运行时出现,然后在退出时消失?为什么会消失?
    • 不,我的意思是,如果您在对话框发生之前关闭对话框,您将避免竞争条件,然后创建一个 onResume 可以毫无问题地引用的新对话框。我想我要说的是摆脱冒犯性的引用。
    • 这就是为什么它是一个“肮脏”的解决方案。比 IMO 屏幕上什么都没有要好。
    【解决方案3】:

    您是使用 Java 平台提供的 Threading 还是使用 Android 便利类?

    我指的是AsyncTask。您很可能在不方便的时间发布 Runnables 时遇到问题。 AsyncTask 类很好地封装了这些特性。子类AsyncTask,指定参数、进度和结果的类型。然后在onPostExecute 方法中隐藏您的对话框,同时在doInBackground 方法中执行后台工作。

    示例代码:

    AsyncTask<Void, Void, Void> parseTask = new AsyncTask<Void, Void, Void>() {
    
        @Override
        protected void onPostExecute(Void result) {
            // Dismiss the progress dialog
            dismissDialog(PROGRESS_DIALOG);
        }
    
        @Override
        protected Void doInBackground(Void... params) {
            // Do background work                
            return null;
            }
    };
    
    // Start the background thread
    parseTask.execute();
    

    取自实时代码库。也不要觉得太糟糕,并发编程很容易成为更难编程的系统之一。很有希望您能够识别和识别竞态条件。

    【讨论】:

    • 我正在使用“线程”类,我相信它是由 Java 平台提供的。您指的是哪些 Android 便利类?
    • 我不明白使用 AsyncTask 如何解决保证在 onResume 之前完成并且仍然显示进度对话框的问题。能做到吗?
    • 仅仅使用 AsyncTask 并不能解决您的问题,但是将竞态条件代码移动到 onPostExecute 函数将确保它在后台线程加载的数据有效之前不会运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多