天天看點

android開發之widget控件突然停止更新的原因

     在android中開發widget控件的時候在appwidget-provider元素中有個屬性android:updatePeriodMillis控制widget控件多長時間重新整理一次,但是在1.6以後的版本中,谷歌從省電的方面考慮規定,當updatePeriodMillis的設定的值小于半個小時時,就會失效。也就是通過設定這個屬性值,最短的更新間隔是半小時。但是我們有時候做的一些應用,比如時鐘之類的必須要在極端的時間内重新整理,必須另辟蹊徑。網上流傳的大都是這麼幾種方法:

1通過自己發送android.appwidget.action.APPWIDGET_UPDATE這個廣播重新整理,但是他會使所有的桌面widget控件重新整理

 2 通過自己發送自定義的廣播重新整理

關鍵在于在哪裡發送廣播,有這麼幾種選擇

1在OnEnable中開啟定時線程發

2單開一個service發

3用alarm定時發

後兩種是可行的,第一種方法雖然看起來可行但是有一個bug,如果不解決就會發現自己的widget在運作了一段時間後莫名其妙的的停止了運作。我當時發現總是過一段時間莫名其妙的停止運作後很苦惱,找不到原因,但是系統每半小時的android.appwidget.action.APPWIDGET_UPDATE廣播還是能正常啟動,後來在全局的logcat裡發現停止運作前有一個程序向widget的程序發送了一個信号,signal:9,經過查找後在linux程序通信中發現9号信号就是強制結束程序的信号,可是為什麼總是向widget程序發送這個信号呢,後來想起來AppWidgetProvider是BroadCastReceiver繼承過來的,而BroadCastReceiver的說明裡有這麼一段話:

BroadcastReceiver如果需要完成一項比較耗時的工作 , 應該通過發送 Intent 給 Service, 由 Service 來完成 . 這裡不能使用子線程來解決 , 因為 BroadcastReceiver 的生命周期很短 , 子線程可能還沒有結束

BroadcastReceiver 就先結束了 .BroadcastReceiver 一旦結束 , 此時 BroadcastReceiver 的

所在程序很容易在系統需要記憶體時被優先殺死 , 因為它屬于空程序 ( 沒有任何活動元件的程序 ). 如果它的宿主程序被殺死 , 那麼正在工作的子線程也會被殺死 . 是以采用子線程來解決是不可靠的 。

關鍵原因在于widget所在程序屬于沒有活動元件的空程序,是以被殺,要想不被殺,是他擁有一個活動元件就行,比如service,雖然這樣還會被殺死,但是比起之前2、3個小時就被殺掉一次的頻率就小多了。而且可以提高service優先級。

綜上所述要想而是用線程發送廣播的方法來更新widget的同時要注意不能使得widget所在的程序成為空程序。不然非常容易被系統清理掉。