請將要執行很久的程式碼,放在 Service 中執行

Run your time-consuming jobs in Service

請將要執行很久的程式碼,放在 Service 中執行

在你研讀 Android 文件時,應該會注意到,千萬不能將要執行很久的程式碼放在 Main ( or UI) Thread 中執行,要不然一定會發生 ANR (Android is Not Responding) 錯誤。要避免 ANR 錯誤,對於所有可能會執行超過 5 秒的工作,例如網路或資料庫的存取、音樂的播放等等,你都要自行建立一個新的 Thread 物件,並將該費時的工作放在 Thread.run() 中執行。

其實,光將費時的程式碼放在 Thread.run() 中執行,還是不夠的,他只解決一半的問題。如果你不知道我為什麼會這麼說的,請先讀一下 記得要在程式中,處理鍵盤開啟或關閉的動作 這篇。

讀完後,你知道原因了嗎?當使用者打開或關閉鍵盤時,使用者看到的只是螢幕畫面的旋轉。但是,從程式面來看,Activity 已經經歷了一次生死輪迴。Activity 先被殺掉,再重新建立一個新的。那就代表,這個新建立的 Activity,再也不能和原先還正在執行工作的 Thread ,相互溝通,傳遞資料。

用個例子來說明,你可能會更清楚些。例如,你的程式正在執行一個下載檔案的工作。為了讓使用者清楚,目前的下載的進度。你應該會用個 Progress Dialog,顯示目前已經下載的百分比。如果就在此時,使用者打開鍵盤,你猜會發生什麼事?我想你程式上,原來那個顯示下載進度的 Progress Dialog,應該會不見了。負責下載的 Thread,可能還正在執行中(如果你沒在 onStop() 或 onDestroy() 中,停止 Thread 的執行)。可是,從你的 UI 的呈現,使用者會認為剛剛的那個下載的工作,已經被停下來。

要怎麼解決這個問題?我會建議你,不僅要將費時的工作放在 Thread.run() 中執行,還要將這個 Thread 放在 Service 中執行。因 為,當螢幕要旋轉時,系統只會殺掉 Activity Stack 中,最上面的那一個 Activity,並不會對扮演執行 background task 的 Service 採取任何的動作。Service 和 Thread 還是可以安穩地繼續執行下載的工作,而被系統重起的 Activity,也可以透過 Service 提供的 remote interface,與 Service 進行 IPC (interprocess communication),以獲取目前下載的進度與執行情形。

想更進一步瞭解實作的你,我建議你先研讀 Android 中 Music 這個程式的原始碼。另外想要知道如何與 Service 進行 IPC 的你,請閱讀 Android 文件中的 <sdk_path>/docs/reference/aidl.html 文件,我覺得這篇寫得還算清楚詳細,值得一讀。

你可能感兴趣的:(service)