Getting out of memory error while starting a Activ

2019-02-15 11:42发布

I am working on an app where one activity is a very complex code with different views inflated in a single layout like webview(which is using html files from sdcard with images),imageviews,scrolls.At starting this Activity I am getting these errors.

        E/AndroidRuntime(600): Caused by: java.lang.reflect.InvocationTargetException
        E/AndroidRuntime(600):  at java.lang.reflect.Constructor.constructNative(Native Method)
        E/AndroidRuntime(600):  at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
        E/AndroidRuntime(600):  at android.view.LayoutInflater.createView(LayoutInflater.java:586)
        E/AndroidRuntime(600):  ... 29 more
        E/AndroidRuntime(600): Caused by: java.lang.OutOfMemoryError
        E/AndroidRuntime(600):  at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
        E/AndroidRuntime(600):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:483)
        E/AndroidRuntime(600):  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:351)
        E/AndroidRuntime(600):  at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
        E/AndroidRuntime(600):  at android.content.res.Resources.loadDrawable(Resources.java:1935)
        E/AndroidRuntime(600):  at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
        E/AndroidRuntime(600):  at android.view.View.<init>(View.java:2785)
        E/AndroidRuntime(600):  at android.view.View.<init>(View.java:2722)
        E/AndroidRuntime(600):  at android.view.ViewGroup.<init>(ViewGroup.java:379)
        E/AndroidRuntime(600):  at android.widget.RelativeLayout.<init>(RelativeLayout.java:174)
        E/AndroidRuntime(600):  ... 32 more

How to solve this problem I have tried this code but still not knowing what to do?

 @Override
    protected void onDestroy() {
    super.onDestroy();

    unbindDrawables(findViewById(R.id.rootView));
    System.gc();
    }

    private void unbindDrawables(View view) {
        if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
        ((ViewGroup) view).removeAllViews();
        }
    }

What is the possible way to solve this problem? Please Help

3条回答
倾城 Initia
2楼-- · 2019-02-15 12:23

You get the OutOfMemoryException if the image pixels exceeds the limit.(the maximum resolution is 2048*2048)

You can reduce the Image's pixels by using Bitmapfactory.Options -

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap myBitmap = BitmapFactory.decodeFile(mUri.getPath(),options);
Drawable d = new BitmapDrawable(Resources.getSystem(),myBitmap);
updateDrawable(d);

While using your images in the activity reduce their resolution.

Note - inSampleSize=2 means it reduces the size by 1/2 and the resolution by 1/4.

Try to keep the value of inSampleSize in power of 2 too get best results.

Hope, it works out for you. Any query, please comment.

查看更多
乱世女痞
3楼-- · 2019-02-15 12:38

The best way to optimize memory usage with bitmaps in your case is to save a list of your ImageViews make this before call finish() for every ImageView:

((BitmapDrawable) myImageView.getDrawable()).getBitmap().recycle();
myImageView = null;

Use too the code in onPause code, with the main layout of your activity having the id top_layout:

@Override
protected void onPause() {
    super.onPause();
    unbindDrawables(findViewById(R.id.top_layout));
    System.gc();
}
查看更多
Emotional °昔
4楼-- · 2019-02-15 12:44

After searching and seeing the above answer I have written a simple snippet by just modifying code from Android User.I have used this which is successfully working.This code setCallback the view's background and even recycle all the present bitmap used.

     @Override
        protected void onDestroy() {
        super.onDestroy();

        unbindDrawables(findViewById(R.id.rootView));
        System.gc();
        }

 static void unbindDrawables(View view) {
     try{
     System.out.println("UNBINDING"+view);
            if (view.getBackground() != null) {

                ((BitmapDrawable)view.getBackground()).getBitmap().recycle();


                view.getBackground().setCallback(null);
                view=null;
            }

            if (view instanceof ViewGroup) {
                for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
                unbindDrawables(((ViewGroup) view).getChildAt(i));
                }
            ((ViewGroup) view).removeAllViews();
            }

    }catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();
    }
 }   

EDIT:

A new thing I discovered today using images less than 20 kb of size is good for memory-optimization and less u have to go through out-of-memory error.

查看更多
登录 后发表回答