BitmapFactory показывает OutOfMemoryError при чтении всех изображений с sdcard0

Я пытаюсь получить все изображения с sdcard0 с помощью метода адаптера - getView(). Я пытаюсь заполнить представление галереи, которое устарело, но в документе с требованиями подразумевается, что я использую представление галереи. Как я вижу, если изображений очень мало, то этот подход работает, но если на sdcard0 больше 10 или около того изображений, я получаю исключение OutOfMemoryException. Может ли кто-нибудь помочь мне повторно использовать память для объекта Bitmap, который я читаю из файла и создаю

"Bitmap bitmap = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile((file.getPath())), 275, 210);".

Поскольку я создаю много объектов Bitmap, мне не хватает памяти. Все изображения имеют формат jpg, сняты с помощью камеры устройства и имеют средний размер 3,5 МБ. Это Samsung Galaxy S4, на котором я тестирую.

Button btnFetch;
ImageView ivLoad;
Gallery galView;
MyAdapter adapter;
static Context context;
File[] files;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_sdcard);
    context = SDCardActivity.this;
    btnFetch = (Button) findViewById(R.id.btnFetch);
    ivLoad = (ImageView) findViewById(R.id.ivLoad);
    galView = (Gallery) findViewById(R.id.galView);

    loadingMyGalleryView();
    adapter = new MyAdapter();
    galView.setAdapter(adapter);

    galView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

            File file = files[position];
            Bitmap bm = BitmapFactory.decodeFile(file.getPath());
            ivLoad.setImageBitmap(bm);
        }
    });
}

private void loadingMyGalleryView() {
    if (android.os.Environment.getExternalStorageState().equals(
            android.os.Environment.MEDIA_MOUNTED)) {

        // It have to be matched with the directory in SDCard
        File f = new File(Environment.getExternalStorageDirectory()
                + File.separator + "DCIM/Camera");
        boolean exist = f.exists();
        Log.d("loki", "Reached Line 80" + exist);
        if (exist) {
            Log.d("loki", "Reached line 82");
            files = f.listFiles();
            for (int i = 0; i < files.length; i++) {
                Log.d("loki", "" + files[i]);
            }
        }
    }
}

class MyAdapter extends BaseAdapter {

    @Override
    public Object getItem(int position) {
        return files[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getCount() {
        // Log.d("loki", ""+files.length);
        return files.length;

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ImageView image = new ImageView(context);
        File file = files[position];
        Bitmap bitmap = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile((file.getPath())), 275, 210);
        image.setImageBitmap(bitmap);
        image.setAdjustViewBounds(true);
        image.setScaleType(ImageView.ScaleType.FIT_CENTER);
        return image;
    }
}

LogCat показывает:

08-10 12:15:38.403: E/AndroidRuntime(21585): FATAL EXCEPTION: main
08-10 12:15:38.403: E/AndroidRuntime(21585): java.lang.OutOfMemoryError
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:529)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:302)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:328)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at com.example.sdcard.SDCardActivity$MyAdapter.getView(SDCardActivity.java:140)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.AbsSpinner.onMeasure(AbsSpinner.java:193)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.View.measure(View.java:15518)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:681)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.View.measure(View.java:15518)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4825)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.View.measure(View.java:15518)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.LinearLayout.measureVertical(LinearLayout.java:847)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.View.measure(View.java:15518)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4825)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2313)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.View.measure(View.java:15518)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1874)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1089)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1265)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.Choreographer.doCallbacks(Choreographer.java:562)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.Choreographer.doFrame(Choreographer.java:532)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.os.Handler.handleCallback(Handler.java:725)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.os.Handler.dispatchMessage(Handler.java:92)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.os.Looper.loop(Looper.java:137)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at android.app.ActivityThread.main(ActivityThread.java:5195)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at java.lang.reflect.Method.invokeNative(Native Method)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at java.lang.reflect.Method.invoke(Method.java:511)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
08-10 12:15:38.403: E/AndroidRuntime(21585):    at dalvik.system.NativeStart.main(Native Method)

person LokiDroid    schedule 10.08.2013    source источник


Ответы (2)


Ваш адаптер не работает, так как вы неправильно обрабатываете convertView (если на самом деле вы здесь ничего не делаете), поэтому для каждой строки вы создаете новое представление вместо повторного использования существующих, которые потребляют память. То есть:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View v = convertView;

    if(v == null){
       // Inflate View from xml or create by code
       v = .....
    }

    // display your thumbnail
    ....
}

Вот чтение: http://android-decoded.blogspot.com/2011/12/so-what-exactly-is-convertview.html

person Marcin Orlowski    schedule 10.08.2013

В getView() повторно используйте второй аргумент, т.е. convertView, чтобы сохранить память для вашего приложения. чтобы прочитать больше документации, нажмите здесь

person Akbar Sha Ebrahim    schedule 20.08.2013