简体   繁体   English

Phonegap:关闭DroidGap活动后javascript计时器仍在运行

[英]Phonegap: javascript timer still running after closing DroidGap activity

I'm working in an Android WebApp using Phonegap. 我正在使用Phonegap在Android WebApp中工作。 To exit the application, I'm calling navigator.app.exitApp from JavaScript code. 要退出应用程序,我将从JavaScript代码调用navigator.app.exitApp

I tried to find the documentation page for this method, but it does not exist. 我试图找到此方法的文档页面,但它不存在。 Then I downloaded the Phonegap source code for Android, but I got lost without finding where and how does this library exit the app from native code. 然后我下载了适用于Android的Phonegap源代码,但是我没有找到该库从本机代码退出应用程序的位置和方式。 I've no time for this so I decided to test it on my own. 我没有时间这样做,所以我决定自己测试一下。

My app has a single DroidGap activity (launched with singleInstance flag), but also a Service and a Broadcast Receiver. 我的应用程序有一个DroidGap活动(使用singleInstance标志启动),还有一个服务和一个广播接收器。 The user must be able to close the GUI, but I'd like to keep the services and everything else running. 用户必须能够关闭GUI,但我想保持服务和其他一切运行。 So what I'd like to do is to finish only the activity, instead of calling System.exit . 所以我想做的只是完成活动,而不是调用System.exit

Now here comes the odd part. 现在这里有奇怪的部分。 I've tested this in a simulator and the DroidGap activity seems to close the way I want it to (onDestroy is fired) and the services are kept running. 我已经在模拟器中对此进行了测试,并且DroidGap活动似乎以我想要的方式关闭(onDestroy被触发)并且服务保持运行。 But, despite the activity is closed, and the app icon is no longer shown in the task manager, somehow a JavaScript timer is still running. 但是,尽管活动已关闭,并且任务管理器中不再显示应用程序图标,但JavaScript计时器仍在运行。 I've triple-checked this. 我已经三次检查了这个。 I'd like to believe the activity is in the background, but it can't be: it is launched as singleInstance, and when I open the app again it shows the initial page (it was closed in a different page). 我想相信活动是在后台,但它不能是:它是作为singleInstance启动的,当我再次打开应用程序时,它会显示初始页面(它在不同的页面中关闭)。

Why does this happens? 为什么会这样? Should I code a plugin to directly call finish over the activity? 我应该编写一个插件来直接调用活动finish吗?

Thanks in advance. 提前致谢。

I've been investigating this for a couple hours, so I'll post here my findings. 我一直在调查这几个小时,所以我会在这里发布我的发现。

In every Android WebApp, not only Phonegap apps, whenever you have a WebView two threads are spawned: WebViewCoreThread and WebViewWorkerThread . 在每个Android WebApp中,不仅是Phonegap应用程序,每当你有一个WebView产生两个线程时: WebViewCoreThreadWebViewWorkerThread They are shown in DDMS. 它们显示在DDMS中。 I've been reading the Android sources and I've tracked the creation of this thread down to the WebViewCore.java file. 我一直在阅读Android源代码,我已经跟踪了这个线程的创建,直到WebViewCore.java文件。 Apparently only two threads per application process are started, and they are shared by every WebView in the app. 显然,每个应用程序进程只启动两个线程,并且它们由应用程序中的每个WebView共享。

IMHO, the fact that using a View in a screen means spawning threads is very bad design. 恕我直言,在屏幕上使用View意味着产生线程是非常糟糕的设计。 If this field needs to do things as complex as starting a thread, then it should have been better designed as WebViewActivity or WebWiewFragment instead. 如果此字段需要执行像启动线程那样复杂的事情,那么它应该更好地设计为WebViewActivity或WebWiewFragment。 In any case, the class that creates the thread should also be responsible to finish it when it is no longer needed. 在任何情况下,创建线程的类也应该负责在不再需要它时完成它。 This unfortunately is not the case. 不幸的是,事实并非如此。

When the activity containing the WebView is closed but the application process is still running (maybe because you have other components like services, or perhaps the OS has not killed it yet), these threads are kept running. 当包含WebView的活动关闭但应用程序进程仍在运行时(可能因为您有其他组件,如服务,或者操作系统尚未杀死它),这些线程将继续运行。 The core thread will continue executing the timers you set in your app. 核心线程将继续执行您在应用中设置的计时器。 When the activity is created again, the threads are reused. 再次创建活动时,将重用线程。

As a side note, notice how this allows running javascript code in background without having to keep an activity displayed. 作为旁注,请注意这是如何允许在后台运行javascript代码而不必显示活动。

I tried some of the workarounds for a regular WevView exposed in this question: WebView threads never stop (WebViewCoreThread, CookieSyncManager, http[0-3]) , 我尝试了在这个问题中暴露的常规WevView的一些变通方法: WebView线程永远不会停止(WebViewCoreThread,CookieSyncManager,http [0-3])

but for some unknown reason it does not work with Phonegap. 但由于某些未知原因,它不适用于Phonegap。 I tried overriding my DroidGap subclass like this: 我尝试覆盖我的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();
}

So what I finally did is to make sure all timers are cancelled from JavaScript code before exiting the app. 所以我最终做的是确保在退出应用程序之前从JavaScript代码中取消所有计时器。 However, one would expect this fixed in the Android OS code, or patched in Phonegap, because even in the best case these threads are wasting resources that really are not needed when there's no web page being shown. 但是,人们会期望这在Android操作系统代码中得到修复,或者在Phonegap中修补,因为即使在最好的情况下,这些线程也浪费了在没有显示网页时真正不需要的资源。 And in the worst scenario, some DOM related JavaScript code could crash. 在最糟糕的情况下,一些与DOM相关的JavaScript代码可能会崩溃。

You need to kill the timer explicitly, right before calling navigator.app.exitApp() . 您需要在调用navigator.app.exitApp()之前显式地终止计时器。 This issue is also discussed here . 这里也讨论了这个问题。

Hope this helps...:) 希望这可以帮助...:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM