当从sdcard0读取所有图像时,BitmapFactory显示OutOfMemoryError

时间:2013-08-10 07:17:26

标签: android out-of-memory bitmapfactory

我正在尝试使用adapter - getView()方法从sdcard0中检索所有图像。我正在尝试填充一个不推荐使用的图库视图,但是需求文档意味着我使用了库视图。正如我所看到的,如果图像非常少,那么这种方法可行,但如果sdcard0上的数字超过10个左右,那么我会得到OutOfMemoryException。有人可以帮我重用我从文件中读取并创建

的Bitmap对象的内存
"Bitmap bitmap = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile((file.getPath())), 275, 210);".

由于我正在创建大量的Bitmap对象,因此我的内存不足。这些图像都是jpg格式,使用设备上的摄像头点击,平均大小为3.5 MB。它是我正在测试的三星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)

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

getView()中重用第二个参数,即convertView来保存应用程序的内存。  to read more documentation click here