0

2 つのクラスがあります。複数のウィジェットを制御するアクティビティ クラスと、スレッドを実装するカスタム SurfaceView クラスです。(非常に一般的な)。Activity クラスのさまざまなウィジェットで更新したいスレッドで特定の値が変更されるたびにトリガーできるシンプルなカスタム リスナーを SurfaceView クラスに実装しました。

public class MyActivity extends Activity{

    CustomView myThreadView = (CustomView)findViewById(...);

    myThreadView.setListener(new OnStatChangeListener(){
        public void onChange(int change){
            //Change various widgets based on value fed in.
        }
    });

    // All of the other things (View setups, listeners, onCreate, etc.)
}

スレッドクラス:

public class CustomView extends SurfaceView implements Runnable(){
    //.. The usual thread and View stuff.

    public sListener;

    public interface OnStatChangeListener {
        public onChange(int change);
    }

    public void setListener(OnStatChangeListener oscl){
        sListener = oscl;
    }

    public void externalAccessMethod(){
        // Some thing changes a stat that is reflected in the Activity's widgets.
        sListener.onChange(value);
    }

    public void methodRunByThread(){
        // Something else changes that I want to update.
        sListener.onChange(value);
    }

    // Everything else (not relevant).
}

アクティビティのクラスによって呼び出されたメソッドから onChange を呼び出すたびに、問題なく動作します。ただし、スレッド自体がその状態 (私の場合は redraw メソッド) を更新し、onChange メソッドを呼び出すと、CalledFromWrongThread 例外が発生します。なぜ一方が機能するのに他方が機能しないのか、別のスレッドからウィジェットの更新を実際に実装するためのベストプラクティスは何かを誰かが説明できますか? いずれにせよ値をいつ更新するかを正確に知っているので、Activity の個別のハンドラ スレッドは必要ないようです。

4

1 に答える 1

0

UI スレッドからしかビューにアクセスできないためです。アプリケーションごとに 1 つの UI スレッドがあります。ここで、別のスレッドからビューにアクセスしますが、これは正しくなく、例外が発生します。

次のいずれかを実行できます。

アクティビティの onChange ですべてを runOnUiThread にラップします

またはそれ以上:

独自のリスナーの代わりにハンドラーを使用します (ある程度の学習が必要ですが、有料です)

于 2012-09-26T19:03:20.050 に答える