【问题标题】:Performing long running operation in onDestroy在 onDestroy 中执行长时间运行的操作
【发布时间】:2012-02-28 09:23:34
【问题描述】:

我需要在onDestroy()Activity 中执行“长时间运行”的清理操作。最好的方法是什么?

如果我使用Thread 执行此操作,我的onDestroy() 将立即返回;但是 Thread 引用会发生什么?我正在寻找有关我需要在这里注意的任何影响/陷阱/绊脚石的建议,因为我假设即使在 Activity 被销毁后该过程仍然存在。


背景:

我在我的应用程序中使用JmDNS。当用户完成我的应用程序后,我想清理 JmDNS 实例。我使用JmDNS 类的close() 方法来做到这一点。但是,此方法需要 5 秒以上 才能完成。结果,用户在触摸返回键后很长一段时间都在屏幕上看到了我的Activity

我还没有弄清楚为什么close() 需要这么长时间,但同时我也意识到我真的不需要等待关闭成功完成。我所需要的只是一种“触发”关闭并完成它的方法。

【问题讨论】:

  • jmdns 通常用于发现网络服务,我不知道为什么您需要保持它打开并运行直到应用程序最终关闭。我通常在找到远程服务器并完成后立即关闭它,同时提示用户一个 ProgressDialog。
  • 是的,这是我的正常用例。我还有另一个用例,我需要在应用程序的整个生命周期内持续监控发现/丢弃的服务并采取相应措施。

标签: java android multithreading lifecycle jmdns


【解决方案1】:

我最终做了我在问题中提出的问题 - 我启动了一个 Thread 以在 onDestroy() 中执行长时间运行的操作。

我必须考虑的一个情况是,用户甚至在长时间运行完成之前重新打开我的应用程序。在我的应用程序中,这意味着创建了一个新的 JmDNS 实例。所以,我在onDestroy 中分别清理每个实例。

您的用例可能有所不同 - 您可能希望仅在清理线程尚未运行时才启动它(使用 ThreadisAlive() 方法或一些此类技术)。

这里有一些示例代码。要了解“分别清理每个实例”部分,请执行以下步骤:

  1. 启动应用程序
  2. 按返回按钮。您将在 LogCat 中看到清理操作
  3. 重新启动应用程序。
  4. 再次退出应用。现在,您将看到两组清理日志——第一组代表第一个实例的清理;第二个集合对应第二个实例。

    public class DelayedExitActivity extends Activity {
    
        private static final String LOG_TAG = "DelayedExit";
        private final  Runnable longOperation = new Runnable(){
            @Override
            public void run() {
                for (int i=0 ; i < 50; i++){
                    Log.d(LOG_TAG, "Iteration "+i);
                    try {
                        Thread.sleep(2 * 1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        };
        private Thread longThread ;
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
        }
    
        @Override
        protected void onDestroy() {
            if(longThread == null){
                longThread = new Thread(longOperation);
            }
            longThread.start();
            super.onDestroy();
        }
    }
    

【讨论】:

  • 只是提醒那些阅读此解决方案的人。它会起作用,但请注意,这将保留对活动的隐式引用,并且只要此操作处于活动状态,您就会有内存泄漏。
【解决方案2】:

尝试在onBackPressed() 中启动您的线程,并在您的线程结束时调用destroy()

【讨论】:

  • 你不是说我应该在线程结束后调用finish() 吗?在这种情况下,用户在按下 Back 键时会看到什么?
  • 是的,我的意思是你应该调用finish()。 Yuo 可以在按返回键时显示 ProgressDialog 或其他任何内容。
  • 我不愿意让用户等待我的应用程序关闭!由于我对清理操作的结果不感兴趣,所以我想知道是否可以在一个线程中开始清理并简单地继续 Activity 销毁。这样,当清理在后台进行时,用户会立即“退出”应用程序。我唯一关心的是那个后台线程会发生什么;如果用户在后台线程完成之前重新启动我的应用程序会发生什么。
  • 如果您的应用程序不使用与线程相同的东西,什么都不会发生
  • 这不会处理切换到另一个活动并稍后从停止状态销毁。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-15
  • 1970-01-01
相关资源
最近更新 更多