2012-05-05 78 views
0

從活動中,我創建一個處理程序來每隔45秒觸發一次我的AsyncTask,以刷新ListView的DataAdapter的內容。 AsyncTask工作良好,並通過ProgressUpdates和Toast消息讓用戶瞭解進度。Android屏幕旋轉觸發多個AsyncTask線程

由於線程的doInBackground被觸發並遺忘且不可重用,我不得不從我的Hander創建一個每45秒觸發一次的AsyncTask實例。問題是當屏幕旋轉時,然後我得到併發消息,因爲Hander被重新創建並創建了一個新的AsyncTask實例,所以友好的用戶通過ProgressUpdates和Toast消息的進度是壓倒性的,並且使得利用ListView變得困難。

請不要將此建議爲解決方案:android:screenOrientation =「portrait」不是一個選項。

對於必須頻繁運行的東西,我應該使用自定義線程而不是AsyncTask類嗎?待辦事項:未顯示,我必須稍後從Sensor的onSensorChanged事件更新Adapter以更新ListView中每個位置的方位,我將在單獨的AsyncTask類上運行該方法,因爲我不需要每次都通知用戶設備軸承已經改變。

由於AsyncThread無法重用,我是否全部做錯了?簡而言之,在這樣做時,讓Activity刷新ListView並保持UI線程的最佳方式是什麼?

+0

你能告訴我們你的活動的onCreate()和onStart()方法嗎? –

回答

1

問題是,當屏幕旋轉,然後我得到併發消息,因爲吊手被重新創建並創建了AsyncTask的新實例。

原因從API Activity - Configuration Changes報價:

除非你指定,配置變化(如屏幕方向,語言,輸入設備等的變化)會導致您的當前活動被銷燬,根據情況經歷onPause(),onStop()和onDestroy()的正常活動生命週期過程。

因此,每個對象都有一個活動範圍生命週期(即活動類中定義的Handler,AsyncTask等)受到此活動重新消費的影響。但是,您可以繞過這個活動娛樂,在活動的後段所述 - 配置改動部分:

在某些特殊情況下,你可能想繞過基於一個或多個類型的配置重新啓動活動變化。這是通過清單中的android:configChanges屬性完成的。對於任何類型的配置更改,如果您在那裏處理,則會接到對當前活動的onConfigurationChanged(配置)方法的調用,而不是重新啓動。但是,如果配置更改涉及任何您不處理的操作,則該活動仍將重新啓動,並且不會調用onConfigurationChanged(Configuration)。

與主題無關,但作爲一種良好實踐,當活動即將完成時(即在onDestroy()方法中),應該始終銷燬已使用的對象(Handler,AsyncTask等)。

對於必須頻繁運行的東西,我應該使用自定義線程而不是AsyncTask類嗎?

的AsyncTask是很方便,但不適合用於週期性的任務,我會用ScheduledExecutorService的或TimerTask的在這種情況下,檢查了my answer here示例代碼。

+0

感謝約克,在進一步閱讀之後,我沒有使用最好的線程模型來完成這個任務,並且發現Timer會更適合我所要完成的任務。 這是AsyncTask的主要參考資源:http://www.codeproject.com/Articles/162201/Painless-AsyncTask-and-ProgressDialog-Usage – CampbellGolf

+0

我也發現這在確定TimerTask或ScheduledExecutorService之間有用: http://stackoverflow.com/questions/409932/java-timer-vs-executorservice – CampbellGolf

0

你可以請張貼一下你的代碼嗎?瞭解你的問題在哪裏可能是有用的。

由於約克已經指出,你應該使用TimerTask。它似乎更適合你正在嘗試做的事情。

如果它是創造你可以嘗試這樣的事情probleme處理程序的新實例的創建:

private Handler mHandler = null; 

@Override 
public void onCreate(Bundle _savedInstanceState) { 
    super.onCreate(_savedInstanceState); 
    setContentView(R.layout.my_layout); 

    if (mHandler == null) { 
     // TODO create your handler here 
    } 
} 

編輯: 您可以測試_savedInstanceState == NULL了。
_savedInstanceState用於保存活動的狀態,因此轉動手機不應該成爲問題了。但是,如果您離開活動並返回到它,它將創建一個新的處理程序(除非將它作爲靜態變量實例化)。

+0

是的,我同意約克,我要去使用計時器來訪問。順便說一句,我沒有嘗試你的建議來檢查,如果mHandler在創建Handler的新實例之前,它創建一個新的Runnable實例,但是我仍然有旋轉多個AsynTask線程的問題,並且我可以很容易地崩潰應用程序通過翻轉手機來回: – CampbellGolf

+0

致命異常:主要 顯示java.lang.NullPointerException 在com.echo5.appname.ActivityStationsList.onTaskComplete(ActivityStationsList.java:152) 在com.echo5.appname.THREADS.AsyncTaskManager。的onComplete(AsyncTaskManager.java:61) 在com.echo5.appname.ActivityStationsList $ UpdateStationTask.onPostExecute(ActivityStationsList.java:573) 在com.echo5.appname.ActivityStationsList $ UpdateStationTask.onPostExecute(ActivityStationsList.java:1) 在android.os.AsyncTask.finish(AsyncTask.java:417)在Android.os.AsyncTask.access $ 300(AsyncTask.java:127) – CampbellGolf

+0

at android.os.AsyncTask $ InternalHandler.handleMessage(AsyncTask.java:429) at android.os.Handler.dispatchMessage(Handler.java:99 ) at android.os.Looper.loop(Looper.java:130) at android.app.ActivityThread.main(ActivityThread.java:3687) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:507) at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:842) at com.android.internal.os.ZygoteInit。 main(ZygoteInit.java:600) at dalvik.system.NativeStart.main(Native Method) – CampbellGolf