1

アクティビティのonCreateメソッドで、onSharedPreferenceChangeListenerを登録します。アクティビティ自体は、OnSharedPreferenceChangeListenerを実装します。

プリファレンスが更新されると、次のメソッドが呼び出されます。

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

}

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

このコードは、特定のプロパティが更新された後、コンテナビューからすべてのビューを削除します。Android 4デバイスでは問題なく動作しますが、Android2.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スレッドで実行されることを確認するにはどうすればよいですか?これを修正する方法についての助けをいただければ幸いです。

4

1 に答える 1

1

問題は、どういうわけかあなたが新しいスレッドに迷い込んだことです:

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

UIコマンドがUIスレッドにあることを確認する1つの方法は、UIハンドラーを使用することです。(思ったほど難しくはありません。)removeViews()Runnableの中に入れて、post()任意のビューで使用するだけです。そのようです:

Runnableを作成します。

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

UIスレッドに投稿します。

if(key.equals(Configuration.PREF_TIMETABLE_UPDATING)){
    container.post(runnable);
}
于 2013-03-24T15:42:18.880 に答える