【问题标题】:Phonegap: javascript timer still running after closing DroidGap activityPhonegap:关闭 DroidGap 活动后,javascript 计时器仍在运行
【发布时间】:2013-04-09 11:09:55
【问题描述】:

我正在使用 Phonegap 开发 Android WebApp。要退出应用程序,我从 JavaScript 代码调用 navigator.app.exitApp

我试图找到此方法的文档页面,但它不存在。然后我下载了 Android 的 Phonegap 源代码,但我迷路了,没有找到这个库在哪里以及如何从本机代码中退出应用程序。我没时间做这个,所以我决定自己测试一下。

我的应用有一个 DroidGap 活动(使用 singleInstance 标志启动),还有一个服务和一个广播接收器。用户必须能够关闭 GUI,但我想保持服务和其他一切运行。所以我想做的是只完成活动,而不是调用System.exit

现在奇怪的部分来了。我已经在模拟器中对此进行了测试,DroidGap 活动似乎以我想要的方式关闭(onDestroy 被触发)并且服务保持运行。但是,尽管活动已关闭,并且应用程序图标不再显示在任务管理器中,但不知何故 JavaScript 计时器仍在运行。我已经三重检查了这一点。我想相信活动在后台,但它不可能:它作为单实例启动,当我再次打开应用程序时,它显示初始页面(它在不同的页面中关闭)。

为什么会发生这种情况?我应该编写一个插件来直接调用finish 吗?

提前致谢。

【问题讨论】:

  • 只是为了分享,我也经历过同样的事情。不知何故,即使应用程序关闭并且如果我们有一些计时器(例如使用 setInterval),有时它也会继续运行。我的理论是应用程序已被销毁,但 webview 以某种方式保留在内存中被执行?
  • 我目前正在真机上调试。有一个WebViewCoreThread 在关闭活动后仍在运行。我发现了这个问题,可能相关:stackoverflow.com/q/2040963/813951
  • 这很奇怪。应用销毁后webview怎么还活着?
  • 应用进程没有被破坏,因为有更多的组件在运行。 WebView 和 Activity 被销毁,但与 WebView 关联的线程仍在运行(与您在常规活动中启动新线程并完成活动时相同)
  • 看来你回答了你自己的问题:)

标签: java javascript android cordova exit


【解决方案1】:

我已经调查了几个小时,所以我将在这里发布我的发现。

在每个 Android WebApp 中,不仅是 Phonegap 应用程序,只要您有一个 WebView,就会产生两个线程:WebViewCoreThreadWebViewWorkerThread。它们显示在 DDMS 中。我一直在阅读 Android 源代码,并且我已经将这个线程的创建跟踪到 WebViewCore.java 文件。显然,每个应用程序进程只启动了两个线程,它们由应用程序中的每个 WebView 共享。

恕我直言,在屏幕中使用视图意味着产生线程这一事实是非常糟糕的设计。如果这个字段需要做像启动线程一样复杂的事情,那么它应该被更好地设计为 WebViewActivity 或 WebWiewFragment 。在任何情况下,创建线程的类也应该负责在不再需要它时完成它。不幸的是,事实并非如此。

当包含 WebView 的 Activity 关闭但应用程序进程仍在运行时(可能是因为您有其他组件,如服务,或者操作系统尚未杀死它),这些线程会继续运行。核心线程将继续执行您在应用程序中设置的计时器。再次创建活动时,线程被重用。

作为旁注,请注意这如何允许在后台运行 javascript 代码而不必保持显示活动。

我为这个问题中公开的常规 WevView 尝试了一些解决方法:WebView threads never stop (WebViewCoreThread, CookieSyncManager, http[0-3])

但由于某些未知原因,它不适用于 Phonegap。我尝试像这样覆盖我的 DroidGap 子类:

@Override
public void onDestroy(){
    System.out.println("Activity destroyed");

    if(appView != null){ //This is a protected reference to the `CordovaWebView`, extending `WebView`
        //First attempt
        try {
            Class.forName("android.webkit.WebView").getMethod("onPause", (Class[]) null).invoke(appView, (Object[]) null);
        } catch (Exception e) {             
            e.printStackTrace();
        } 

        //Second attempt
        appView.pauseTimers();          
    }

    super.onDestroy();
}

所以我最终要做的是确保在退出应用程序之前从 JavaScript 代码中取消所有计时器。但是,人们会期望在 Android 操作系统代码中修复此问题,或在 Phonegap 中进行修补,因为即使在最好的情况下,这些线程也会浪费资源,而这些资源在没有显示网页时确实不需要。在最坏的情况下,一些与 DOM 相关的 JavaScript 代码可能会崩溃。

【讨论】:

  • 感谢分享。你是如何设法取消所有计时器的?我的问题是我的 WebView 被一些用户发送到后台并被 Android 系统杀死。我认为不可能手动取消所有计时器...
  • @ottel142 我将开始通过 javascript 文件搜索 setInterval,并确保每个调用结果都存储在一个变量中,以便您以后可以使用 clearInterval 取消它们。与setTimeout 通话相同。另一种可能性是在您的活动的onDestroy 中调用System.exitProcess.killProcess,这应该会杀死整个主进程。如果您需要服务,您可能希望在不同的进程中启动它,以免它与活动一起被杀死。
【解决方案2】:

您需要在调用navigator.app.exitApp() 之前明确地终止计时器。这个问题也在here讨论。

希望这会有所帮助...:)

【讨论】:

  • 谢谢,我会的。但这是一种解决方法。我希望操作系统或 Phonegap 能够处理它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-26
相关资源
最近更新 更多