2013-03-24 98 views
1

在我的Activity的onCreate方法中,我註冊了onSharedPreferenceChangeListener。活動本身實現了OnSharedPreferenceChangeListener。更改共享首選項後更新UI時,應用程序崩潰

更新首選項時,會調用以下方法。

@Override 
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 
    if(key.equals(Configuration.PREF_TIMETABLE_UPDATING)){ 
     resetView(); 
    } 

} 

public void resetView(){ 
    this.container.removeAllViews(); 
} 

此代碼在某個屬性更新後從容器視圖中刪除所有視圖。它的工作原理沒事跟我的Android 4級的設備,但我的Android 2.2.1設備上的應用程序崩潰:

03-24 16:09:00.054: E/AndroidRuntime(1712): FATAL EXCEPTION: AsyncTask #5 
03-24 16:09:00.054: E/AndroidRuntime(1712): java.lang.RuntimeException: An error occured while executing doInBackground() 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.os.AsyncTask$3.done(AsyncTask.java:200) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at java.util.concurrent.FutureTask.setException(FutureTask.java:124) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at java.lang.Thread.run(Thread.java:1102) 
03-24 16:09:00.054: E/AndroidRuntime(1712): Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.view.ViewRoot.checkThread(ViewRoot.java:2824) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.view.ViewRoot.requestLayout(ViewRoot.java:598) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.view.View.requestLayout(View.java:8126) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.view.View.requestLayout(View.java:8126) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.view.View.requestLayout(View.java:8126) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.view.View.requestLayout(View.java:8126) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.widget.ScrollView.requestLayout(ScrollView.java:1200) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.view.View.requestLayout(View.java:8126) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.view.ViewGroup.removeAllViews(ViewGroup.java:2263) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at com.example.TimetableActivity.resetView(TimetableActivity.java:430) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at com.example.TimetableActivity.onSharedPreferenceChanged(TimetableActivity.java:557) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.app.ContextImpl$SharedPreferencesImpl$EditorImpl.commit(ContextImpl.java:2869) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at com.example.MyHelper.setTimetableUpdate(MyHelper.java:145) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at com.example.webservice.task.LessonFetcherTask.doInBackground(LessonFetcherTask.java:33) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at com.example.webservice.task.LessonFetcherTask.doInBackground(LessonFetcherTask.java:1) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at android.os.AsyncTask$2.call(AsyncTask.java:185) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
03-24 16:09:00.054: E/AndroidRuntime(1712):  ... 4 more 

如何確保由OnSharedPreferenceChangeListener調用該方法的UI線程上運行?任何有關如何解決這個問題的幫助將不勝感激!

回答

1

的問題是,不知爲何,你曾流浪到一個新的主題:

Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

的一種方式,以確保UI命令是在UI線程使用UI處理程序。 (這聽起來不那麼難)。只需將removeViews()放入Runnable中,並在任何View上使用post()即可。像這樣:

創建一個Runnable:

Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 
     resetView(); 
    } 
}; 

張貼到UI線程:

if(key.equals(Configuration.PREF_TIMETABLE_UPDATING)){ 
    container.post(runnable); 
} 
+0

非常感謝你,這解決了我的問題! :) – 2013-03-24 16:07:04

相關問題