2013-04-09 67 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