AsyncTask的版本兼容性與target sdk version

AsyncTask的版本兼容性與target sdk version


最近發現了一個奇怪的問題,一處很久前寫的代碼,通過AsyncTask的doInBackground進行後臺處理,突然間不管用了,就是說doInBackground沒有被執行。同事查詢SVN,發現相關代碼沒有過任何更改,經過很久的檢查,發現只有在Manifest中有一處很小的改動,就是添加了targetSDKVersion。將這個屬性去掉,就沒有問題了。

 

通過對源碼和google group以及stackoverflow的各種查找和測試,發現google挖了兩個坑,不幸的是,我們跳了。

 

第一個坑:AsyncTask在Android各個版本中可以算是頻繁修改了,比較各版本代碼發現,修改過多次,而且這種修改會導致很大的差別。最坑的修改是在Android 4.0開始的,AsyncTask的中execute方法的實現在4.0以前是採用Thread pool executor,各個版本對線程池中的可並行線程數限制不同,但畢竟多個Task是多線程並行。而在4.0開始,改爲用serial executor,就是說同一時間只能有一個線程運行,其他線程必須等待該線程完成之後才能開始執行,因此就變成了串行的worker thread。

 

第二個坑:targetSDKVersion,這個屬性其實很多開發者都沒有注意到,Google在官方文檔中的解釋又十分複雜,導致它出了問題就很難定位。總的來說,這個屬性是Google爲了進行兼容性檢查來設置的,有一些API,例如AsyncTask這種,會根據它的設置來選擇執行方式。如果targetSDKVersion設置成了4.0,那麼系統就認爲你的應用在4.0版本上有了足夠的測試,不會有問題,那麼會選擇4.0的各種新特性,就是說用serial executor來實現AsyncTask。如果不加入targetSDKVersion,默認這個值會等於minSDKVersion,這時候系統認爲你沒有在4.0版本上測試,爲了防止出問題,在4.0手機上會採用Thread pool executor來實現AsyncTask。因此就導致了我們之前的問題。

 

Google對AsyncTask增加了一個方法,executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ....);通過這個方法可以強制系統用Thread pool executor實現。但是需要API level 11,調用也會很麻煩。還是要注意邏輯,對長時間佔用背景線程的操作避免用AsyncTask,或者自己寫一個AsyncTask更靠譜一些。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章