2013-04-09 55 views
3

我正在使用Phonegap在Android WebApp中工作。要退出应用程序,我从JavaScript代码中调用navigator.app.exitAppPhonegap:关闭DroidGap活动后javascript定时器仍在运行

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

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

现在来了奇怪的部分。我已经在模拟器中测试了这一点,并且DroidGap活动似乎以我想要的方式关闭(onDestroy被触发)并且服务仍在运行。但是,尽管活动已关闭,并且应用程序图标不再显示在任务管理器中,但某种程度上JavaScript定时器仍在运行。我三重检查了这一点。我想相信这个活动是在后台进行的,但不能这样做:它是作为singleInstance启动的,当我再次打开该应用程序时,它会显示初始页面(它在不同的页面中关闭)。

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

在此先感谢。

+0

只是为了分享,我经历过同样的事情。不知何故,尽管应用程序已关闭,并且如果我们有一些计时器(例如使用setInterval),它有时仍会继续运行。我的理论是,应用程序被销毁,但webview不知何故仍然在执行的内存中? – wmfairuz 2013-04-09 11:15:19

+0

我目前正在真实设备上调试它。有一个“WebViewCoreThread”在关闭活动后仍然在运行。我发现这个问题,可能与此有关:http://stackoverflow.com/q/2040963/813951 – 2013-04-09 11:23:01

+0

这很奇怪。应用程序被销毁后,webview如何仍然活着? – wmfairuz 2013-04-09 11:34:24

回答

0

在调用navigator.app.exitApp()之前,您需要明确杀死定时器。这个问题也讨论here

希望这有助于... :)

+0

谢谢, 我会去做的。但这是一个解决方法。我希望OS或Phonegap来处理它。 – 2013-04-09 11:32:48

+0

我认为PhoneGap应该照顾这个...... – 2013-04-09 12:31:02

2

我一直在研究这个了几个小时,所以我会在这里发布我的发现。

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

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

当包含WebView的活动关闭但应用程序进程仍在运行时(可能是因为您有其他组件,或者操作系统尚未终止它),这些线程仍在运行。核心线程将继续执行您在应用中设置的计时器。当活动再次创建时,线程将被重用。作为一个便笺,请注意这是如何在后台运行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代码可能会崩溃。

+0

感谢您的分享。你是如何设法取消所有定时器的?我有问题,我的WebView被一些用户发送到后台,并被Android系统杀死。我认为没有可能手动取消所有定时器... – ottel142 2013-09-13 17:26:15

+0

@ ottel142我会通过JavaScript文件开始搜索'setInterval',并确保每个调用结果都存储在一个变量中,以便稍后可以用'clearInterval '。与'setTimeout'调用相同。另一种可能性是在你的activity的onDestroy中调用'System.exit'或'Process.killProcess',这会杀死整个主进程。如果您需要某项服务,您可能需要在不同的流程中启动该服务,以便它不会与活动一起被杀死。 – 2013-09-16 09:07:45