1

を使用してRunnablesとして投稿されたメソッドに表示される、オブジェクトの状態が間違っているという非常に奇妙な問題が発生していますHandler.postDelayed。これを使用して、2D描画の描画呼び出しをスケジュールします。この描画コードは、特定の状態フィールド(intやbooleansなど)をチェックします。

描画をスケジュールした後にこれらの状態フィールドが変更される可能性がありますが、すべてのメソッド、遅延呼び出しも同じスレッドで実行されるため(右?)、共有状態による可視性の問題はないはずです。

それでも、抽選をスケジュールする前にフラグを設定し、再度触れないため、フラグがfalseスケジュールされた抽選にある場合は、フラグが表示されない場合があります。trueいくつかの疑似サンプルコード:

public void scheduleDraw() {
    boolean flag = true;
    handler.postDelayed(runnable);
}

runnable = new Runnable() {
    public void run() {
        // flag is false here
    }
}

これはどのように起こりますか?Androidがこれらのメッセージループをどのように実装するかは完全にはわかりませんが、描画をスケジュールするメソッドとスケジュールされたメソッド自体の両方でスレッドIDを確認し、両方が同じスレッド(メインUIスレッド)で呼び出されます。

これは私を夢中にさせています、誰かが助けることができますか?

更新 この問題は、フラグが内部クラスによって1回、外部クラスによって1回チェックされていることが原因であることに気付きました。描画コードは内部クラスの一部として実行され、フラグが正しい状態であると見なされますが、外部クラスは、内部クラスのインスタンスへの参照が含まれていても、常にフラグをfalse(誤った状態)と見なします。私はまだ問題を理解していませんが、それはクラスの入れ子に関連しているようですか?

4

2 に答える 2

1

ここで確認できる問題がいくつかあります。

まず、サンプルコードで、scheduleDraw()内でローカルスコープの変数としてフラグを宣言します。runnableがどのようにアクセスできるかさえわかりません。

それが単なるタイプミスであり、そのフラグがクラス変数であると仮定すると...ブール値をtrueに設定するだけでは、すべてのスレッドがすぐに同じ値を見るわけではありません。Javaでは、一部の変数の書き込みをスレッドローカルでキャッシュできます。つまり、他のスレッドでは実際には一貫性のない値が表示されます。これを回避する1つの方法は、変数volatileを宣言することです。例えば:

private volatile boolean flag;

これを行うと、Javaランタイムに、この変数をスレッドローカルにキャッシュしてはならず、すべての読み取りと書き込みを直接「メインメモリ」に送信する必要があることが通知されます。

別の解決策は、java.util.concurrent.atomicパッケージのAtomicBooleanのインスタンスを使用することです。

private AtomicBoolean flag = new AtomicBoolean();
...
flag.set(true);
于 2012-08-09T19:28:11.437 に答える
0

私は問題を見つけました:外​​部クラスは内部クラスへの参照を保持していました。その内部クラスの複数のインスタンスが一度にアクティブになる(そして切り替えられる)可能性があります。外部クラスのハンドラーを共有しているため、外部クラスは、非アクティブになったばかりのハンドラーコールバックから遅延メッセージを受信することがありました。

現在、外部クラスと内部クラスの間で変数を共有していません。

でもあなたの助けをどうもありがとう!感謝。

于 2012-08-09T21:06:38.367 に答える