0

最近メモリ リーク エラーに悩まされています。サービスから画像をダウンロードして表示するギャラリーを使用してアクティビティを作成しようとしていますが、初めてエラーが発生したときに調査を行いました。 Context の参照か、さまざまなバージョンの Android がメモリ内の画像を管理する方法のいずれかであることが判明しました。コードにいくつかの変更を加えたところ、次のような結果になりました。

public class GalleryView extends Activity {
private LinearLayout imageView;
private String GalleryId;
private ArrayList<Drawable> images = new ArrayList<Drawable>();
private ArrayList<Drawable> thumbs = new ArrayList<Drawable>();
private ArrayList<String> urls;
private AdvertiserDAO aDao = new AdvertiserDAO();


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.galeria);

    setGallery();

    setThumbs();

    Button back = (Button) findViewById(R.id.Back);

    back.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            finish();

        }
    });

    Gallery ga = (Gallery) findViewById(R.id.Gallery01);

    ga.setAdapter(new ImageAdapter(this));

    imageView = (LinearLayout) findViewById(R.id.ImageView01);
    ga.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {

            try {
                imageView.removeAllViews();

            } catch (Exception e) {
                e.getMessage();
            }
            TouchImageView touchImageView = new TouchImageView(
                    GalleryView.this);
            touchImageView.setImageDrawable(images.get(arg2));

            LayoutParams lp = new LayoutParams(LayoutParams.FILL_PARENT,
                    LayoutParams.FILL_PARENT);
            imageView.setGravity(Gravity.CENTER_HORIZONTAL
                    | Gravity.CENTER_VERTICAL);
            touchImageView.setLayoutParams(lp);
            imageView.addView(touchImageView);

        }

    });

}

private void setGallery()  {

    SharedPreferences sp = getSharedPreferences("galeriaId", 0);
    GalleryId = sp.getString("galeriaId", null);

    //retrieves urls of the pictures of the gallery
            urls = aDao.getUrls(GalleryId);

    for (int i = 0; i < urls.size(); i++) {

        Drawable d = ImageOperations(urls.get(i), "image" + i
                + ".jpg");
        images.add(d);
    }

}

private void setThumbs()  {

    SharedPreferences sp = getSharedPreferences("galeriaId", 0);
    GalleryId = sp.getString("galeriaId", null);

            //retrieves the urls of the thumbs of the gallery
    urls = aDao.getThumbs(GalleryId);

    for (int i = 0; i < urls.size(); i++) {

        Drawable d = ImageOperations( urls.get(i), "image" + i
                + ".jpg");
        thumbs.add(d);
    }
}

private Drawable ImageOperations(String url,
        String saveFilename)  {

    InputStream is = (InputStream) fetch(url);

    Drawable d = null;
    try {
        d = new ImageOperationsAsyncTask().execute(is).get();
    } catch (InterruptedException e) {
        Log.e(TAG, e.toString());
        e.printStackTrace();
    } catch (ExecutionException e) {
        Log.e(TAG, e.toString());
        e.printStackTrace();
    }

    return d;

}

public Object fetch(String address)  {

    Object content = null;
    try {
        content = new URLAsyncTAsk().execute(address).get();
    } catch (InterruptedException e) {
        Log.e(TAG, e.toString());
        e.printStackTrace();
    } catch (ExecutionException e) {
        Log.e(TAG, e.toString());
        e.printStackTrace();
    }

    return content;
}

private class ImageOperationsAsyncTask extends
        AsyncTask<InputStream, Integer, Drawable> {

    @Override
    protected Drawable doInBackground(InputStream... params) {

        InputStream is = null;

        for(InputStream i: params){

            is = i;
        }

        Drawable result = Drawable.createFromStream(is, "src");

        return result;
    }

}

private class URLAsyncTAsk extends AsyncTask<String, Integer, Object> {


    @Override
    protected Object doInBackground(String... params) {
        String address = "";
        for (String s : params) {
            address = s;
        }

        URL url;
        Object content = null;
        try {

            url = new URL(address);

            content = url.getContent();

        } catch (MalformedURLException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
        } catch (IOException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
        }

        return content;
    }

}

public class ImageAdapter extends BaseAdapter {

    private Context ctx;
    int imageBackground;

    public ImageAdapter(Context c) {

        ctx = c;
        TypedArray ta = obtainStyledAttributes(R.styleable.Gallery1);
        imageBackground = ta.getResourceId(
                R.styleable.Gallery1_android_galleryItemBackground, 1);

        ta.recycle();
    }

    public int getCount() {

        return images.size();
    }

    public Object getItem(int arg0) {

        return arg0;
    }

    public long getItemId(int arg0) {

        return arg0;
    }

    public View getView(int arg0, View arg1, ViewGroup arg2) {
        ImageView iv = new ImageView(ctx);
        iv.setImageDrawable(thumbs.get(arg0));

        iv.setScaleType(ImageView.ScaleType.FIT_XY);
        iv.setLayoutParams(new Gallery.LayoutParams(150, 120));
        iv.setBackgroundResource(imageBackground);
        return iv;
    }
}}

このコードは、Android 4.1 携帯電話と Android 2.2 エミュレーターで動作しますが、Android 2.3 エミュレーターと携帯電話では、まだログ キャットにメモリ リーク エラーが表示されます。

Android 2.3でしか機能しないのはなぜですか???

編集: LogCat が投稿しているログは次のとおりです。

06-17 14:41:45.050: W/System.err(305): java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
06-17 14:41:45.060: W/System.err(305):  at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:224)
06-17 14:41:45.060: W/System.err(305):  at java.util.concurrent.FutureTask.get(FutureTask.java:83)
06-17 14:41:45.060: W/System.err(305):  at android.os.AsyncTask.get(AsyncTask.java:340)
06-17 14:41:45.060: W/System.err(305):  at directorio.actividades.GalleryView.ImageOperations(GalleryView.java:140)
06-17 14:41:45.060: W/System.err(305):  at directorio.actividades.GalleryView.setGallery(GalleryView.java:107)
06-17 14:41:45.060: W/System.err(305):  at directorio.actividades.GalleryView.onCreate(GalleryView.java:50)
06-17 14:41:45.060: W/System.err(305):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
06-17 14:41:45.060: W/System.err(305):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
06-17 14:41:45.060: W/System.err(305):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
06-17 14:41:45.060: W/System.err(305):  at android.app.ActivityThread.access$1500(ActivityThread.java:117)
06-17 14:41:45.060: W/System.err(305):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
06-17 14:41:45.060: W/System.err(305):  at android.os.Handler.dispatchMessage(Handler.java:99)
06-17 14:41:45.060: W/System.err(305):  at android.os.Looper.loop(Looper.java:130)
06-17 14:41:45.060: W/System.err(305):  at android.app.ActivityThread.main(ActivityThread.java:3683)
06-17 14:41:45.060: W/System.err(305):  at java.lang.reflect.Method.invokeNative(Native Method)
06-17 14:41:45.060: W/System.err(305):  at java.lang.reflect.Method.invoke(Method.java:507)
06-17 14:41:45.060: W/System.err(305):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
06-17 14:41:45.060: W/System.err(305):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
06-17 14:41:45.060: W/System.err(305):  at dalvik.system.NativeStart.main(Native Method)
06-17 14:41:45.060: W/System.err(305): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
06-17 14:41:45.060: W/System.err(305):  at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
06-17 14:41:45.060: W/System.err(305):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
06-17 14:41:45.060: W/System.err(305):  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
06-17 14:41:45.060: W/System.err(305):  at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
06-17 14:41:45.060: W/System.err(305):  at android.graphics.drawable.Drawable.createFromStream(Drawable.java:657)
06-17 14:41:45.060: W/System.err(305):  at directorio.actividades.GalleryView$ImageOperationsAsyncTask.doInBackground(GalleryView.java:195)
4

1 に答える 1

1

ここでの問題は、メモリ リーク自体ではありません。実際の問題は、例外が指し示す問題です。

OutOfMemoryError: ビットマップ サイズが VM の予算を超えています

例外がスローされている行を確認すると、読み込まれている画像に関連していることがわかります。そのイメージは大きすぎて、処理に消費されるメモリがタスクを完了するのに十分ではありません。

この他の回答で良いリファレンスを見つけることができます。適切なアプローチは、問題の発生を防ぐ正しいサンプリングが見つかった場合にのみoptionsBitmapFactoryクラスと画像をいじることです。decodeOutOfMemory

于 2013-06-17T15:13:55.103 に答える