2

描画スレッドの速度を落とさないように、別のスレッドでディスクから画像を読み込もうとしていますが、問題は、ビットマップを保持するオブジェクトが新しいスレッドに転送されるときに、異なるポインターを持つことです。Java が乗算可能なスレッド間でポインターを処理する方法は正確にはわかりませんが、両方のスレッドが同じオブジェクト (浅いコピー) で動作し、スレッド間のオブジェクトの深度コピーではないソリューションを探しています。

これが私のコードです

new LoadImageTask().execute(ThisTimeDrawBitmaps.indexOf(bitmapWrapper), gameEngine);

private class LoadImageTask extends AsyncTask {
    protected BitmapWrapper LoadImage(BitmapWrapper bitmapWrapper, GameEngine gameEngine) {
        //loading the image in a temp object to avoid  fatal error 11
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = true;
        Bitmap tempImage = BitmapFactory.decodeResource(Sceptrum.GetResources, bitmapWrapper.getID(), options);
        tempImage = Bitmap.createScaledBitmap(bitmapWrapper.getBitmap(), (int) (bitmapWrapper.getBitmap().getWidth() * gameEngine.getScale()), (int) (bitmapWrapper.getBitmap().getHeight() * gameEngine.getScale()), false);
        //so that the image can be gc.
        Bitmap RemovePointer = bitmapWrapper.getBitmap();
        //to avoid fatal error 11
        bitmapWrapper.setBitmap(tempImage);
        //removing the old image.
        RemovePointer.recycle();
        return bitmapWrapper;
     }
    @Override
    /**
     * add the bitmapwrapper you want to load and make sure to add the GameEngine as the last parameter.
     */
    protected Object doInBackground(Object... params) {
        for (int i = 0; i < params.length - 1; i++) {
            return LoadImage(ThisTimeDrawBitmaps.get((Integer) params[i]), (GameEngine) params[params.length - 1]);
        }
        return null;
    }
 }

public class BitmapWrapper{
private Bitmap bitmap;
/**
 * Use only to send the bitmap as a parameter. To modify or read data to/from the bitmap use the methods provided by BitmapWrapper.
 * @return
 */
public Bitmap getBitmap() {
    return bitmap;
}
public void setBitmap(Bitmap bitmap) {
    this.bitmap = bitmap;
}
private int id;
public int getID()
{
    return id;
}
private Point originalSize;
public Point getOriginalSize() {
    return originalSize;
}
public BitmapWrapper(Bitmap bitmap, int ID) {
    this.setBitmap(bitmap);
    id = ID;
    originalSize = new Point(bitmap.getWidth(), bitmap.getHeight());
}
public int getWidth()
{
    return bitmap.getWidth();
}
public int getHeight()
{
    return bitmap.getHeight();
}
public void createScaledBitmap(GameEngine gameEngine)
{
    bitmap = Bitmap.createScaledBitmap(bitmap, (int) (originalSize.x * gameEngine.getScale()), (int) (originalSize.y * gameEngine.getScale()), false);
}
public void CreateBitmap()
{
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inScaled = false;
    bitmap = BitmapFactory.decodeResource(Sceptrum.GetResources, id, options);
}
}
4

3 に答える 3

7

これはポインターの問題ではありません (Java ではこのような問題はめったにありません:))。バックグラウンド スレッドで画像をロードする場合は、(静的) AsyncTask を作成する必要があります。これは、実際にビットマップを配置するレイアウト内のビューへの弱い参照を保持します。doInBackground では、画像をロードして返す必要があります。postExecute (UI スレッドで呼び出される) で、doInBackground (ビットマップ) の結果を受け取ります。参照されたビューがまだ存在する (アクティビティがまだ有効である) かどうかを確認した後、ビットマップを使用できます (それらをビューに配置します)。

UI スレッドを除き、他のスレッドから UI 要素を変更することはできません (これは、どの UI フレームワークにも当てはまります)。

于 2013-02-22T09:33:48.133 に答える
0

Containerオブジェクトを紹介してみてください。

public class Container<T> {
    private volatile boolean ready = false;
    private T object;

    public boolean isReady() { 
        return ready; 
    }

    public void setReady(boolean ready) {
        this.ready = ready;
    }

    public T get() {
        return (ready) ? object : null;
    }

    public void set(T object) {
        this.object = object;
    }
}

このコンテナは、次の任意のタイプでインスタンス化できます。

Container<Bitmap> logoContainer = new Container<Bitmap>();
Bitmap logo = logoContainer.get(); // returns null if not yet ready

バックグラウンドスレッドでは、次のように初期化できます。

Container<Bitmap> logoContainer = ... // 
Bitmap b = ... // load
logoContainer.set(b);
logoContainer.setReady(true);
于 2013-02-21T16:11:56.163 に答える
0

で試すことができますvolatile。つまり:

private volatile Bitmap bitmap;

「揮発性と宣言された変数は、すべてのスレッドでデータを同期する必要があります」から:http://www.javaperformancetuning.com/news/qotm030.shtml

于 2013-02-20T20:44:30.397 に答える