2

Android アプリケーションに問題があります。

リストまたはシェイプを常に反復処理し、それらの位置を更新し、リストから項目を削除するスレッドがあります。スレッドの while ループの最後で、postInvalidate() を呼び出して再描画を促します。

ArrayList への変更が行われるコードを次に示します。

Iterator<Shape> iterator = this.myList.iterator();
while (iterator.hasNext()) {
     Shape nextShape = iterator.next();
     nextShape.move();
     if(condition) {
         iterator.remove()
     }
}

onDraw メソッドは、for each ループを使用して、これらの各アイテムを描画します。イテレータを介してリストを変更するだけであるにもかかわらず、onDraw メソッドで同時変更を取得しています。CopyOnWriteArrayList と Collections.synchronized を同じ結果で試しました。

どんな助けでも大歓迎です。

4

1 に答える 1

1

これを解決するにはいくつかの方法があります。1 つは、スレッドと onDraw で同期ブロックを使用することですが、それでは 2 番目のスレッドが UI スレッドと同時に実行されなくなります。

2 つのコレクションを使用するのが最善の方法だと思います。コードは次のようになります

onDraw(){
    synchronized(myList){
        //Do your draw code.  Get the iterator inside this block
    }
}

threadFunction(){
    List threadList;
    while(1){
        //Update threadList, which holds all the objects
        synchronized(myList){
            myList = threadList.copy();  //Do a deep copy, don't just copy over the reference
        }
        postInvalidate();
    }
}

これにより、繰り返しの最後に作成されたリストのコピーに対して描画関数が動作します。ディープ コピーで作業している場合、スレッドが同じリストを変更していないため、同期の問題は発生しません。同期されたブロックは、スレッドが描画中に描画関数のコピーを上書きするのを防ぎます。残っている唯一の問題は、ドローが完了するまでスレッド内のリストの上書きがハングすることですが、それ以上頻繁に更新すると画面に表示されないので、それは許容できると思います.

于 2012-11-15T04:32:22.853 に答える