ViewPager与ImageView的提供和QUOT; java.lang.OutOfMemoryError:位图大小超过VM预算"位图、预算、大小、QUOT

2023-09-05 10:16:08 作者:淺憶流年√

我做了一个 ViewPager 来显示图像。当我提前一些网页,我碰到一个 java.lang.OutOfMemoryError:位图大小超过VM预算错误。

有关于这个问题,更多的问题,但我没有找到解决办法( BitMap.Recycle 的System.gc()等)。如果您有建议或解决方案,请让我知道!

在巴新是628KB,478KB,587KB,132KB,139KB,149KB​​,585KB(崩溃)。

如果您有其他的解决方案(滚动的图像,例如网页),我让满足知道!

ViewPager 刷新无效

我的code:

 包nl.ipear.vngmagazine;
进口android.content.Context;
进口android.graphics.BitmapFactory;
进口android.os.Bundle;
进口android.os.Environment;
进口android.os.Parcelable;
进口android.support.v4.app.FragmentActivity;
进口android.support.v4.view.PagerAdapter;
进口android.support.v4.view.ViewPager;
进口android.util.Log;
进口android.view.LayoutInflater;
进口android.view.View;
进口android.widget.ImageView;

公共类ShowMagazine2扩展FragmentActivity {
    私人ViewPager myPager;
    私人MyPagerAdapter myPagerAdapter;

    私有静态诠释NUM_PAGES = 15;

    / **第一次创建活动时调用。 * /
    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.showmagazine);

        myPager =(ViewPager)findViewById(R.id.viewpager1);
        myPagerAdapter =新MyPagerAdapter();
        myPager.setAdapter(myPagerAdapter);

        返回;
    }

    私有类MyPagerAdapter扩展PagerAdapter {
        @覆盖
        公众诠释getCount将(){
            返回NUM_PAGES;
        }

        @覆盖
        公共对象instantiateItem(查看收集,INT位置){
            字符串位置= Environment.getExternalStorageDirectory()+/ MYDATA /+2012-02 /;

            //膨胀,创建视图
            LayoutInflater layoutInflater =(LayoutInflater)collection.getContext()getSystemService(Context.LAYOUT_INFLATER_SERVICE)。
            查看查看= layoutInflater.inflate(R.layout.magazinepageview,NULL);

            ImageView的ImageView的=(ImageView的)view.findViewById(R.id.magazinePageImage);
            字符串文件名=的String.Format(%s%S%02D%的,定位2012-02_Page_位置+ 1,png格式);
            Log.v(PNG,文件名);
            imageView.setImageBitmap(BitmapFactory.de codeFILE(文件名));

            ((ViewPager)集合).addView(查看,0);

            返回查看;
        }

        @覆盖
        公共无效destroyItem(查看收集,INT位置,对象视图){
            ((ViewPager)集合).removeView((视图));
        }

        @覆盖
        公共布尔isViewFromObject(查看视图,Object对象){
            返回查看==((查看)对象);
        }

        @覆盖
        公共无效finishUpdate(查看为arg0){}

        @覆盖
        公共无效restoreState(Parcelable为arg0,ClassLoader的ARG1){}

        @覆盖
        公共Parcelable saveState和(){
            返回null;
        }

        @覆盖
        公共无效startUpdate(查看为arg0){}
    }
}
 

解决方案

是遵循Mimminito。我建议2页,因为渲染同样快来回3页。

现在,如果你需要的图像,而不滞后和图像在互联网上。确保你下载它,并把一个internalStorageDevice里面,然后再使用它,如果它存在。

我上面的答案也许是不正确的内存泄漏问题。这个新的答案是一个可能的原因内存泄漏是由于图像的高度和宽度的

 专用字节[] resizeImage(byte []的输入){

    如果(输入== NULL){
        返回null;
    }

    位图bitmapOrg = BitmapFactory.de codeByteArray(输入,0,input.length);

    如果(bitmapOrg == NULL){
        返回null;
    }

    INT高= bitmapOrg.getHeight();
    INT宽度= bitmapOrg.getWidth();
    INT newHeight = 250;

    浮动scaleHeight =((浮点)newHeight)/身高;

    //为操作创建矩阵
    字模=新的Matrix();
    //调整位图
    matrix.postScale(scaleHeight,scaleHeight);

    //重新创建新的位图
    位图resizedBitmap = Bitmap.createBitmap(bitmapOrg,0,0,
            宽度,高度,矩阵,真);

    bitmapOrg.recycle();

    ByteArrayOutputStream BOS =新ByteArrayOutputStream();
    resizedBitmap.com preSS(比较pressFormat.PNG,0 / *忽略PNG * / BOS);

    resizedBitmap.recycle();

    返回bos.toByteArray();
}
 

这顶code是rescalling位图newHeight是给位图的新高度。

现在,如果这也不行,我现在100%肯定,OP必须超载ViewPager有更多的意见是,Android的内存可以处理。对此的解决方案是使用一个ViewFlipper和使用I如上所述答案。

I made a ViewPager to display images. When I advance some pages I get an java.lang.OutOfMemoryError: bitmap size exceeds VM budget error.

There are more questions about this issue but I did not find the solution (BitMap.Recycle, System.gc() etc). If you have a suggestion or solution please let me know!

The PNG's are 628KB, 478KB, 587KB, 132KB, 139KB, 149KB, 585KB (crash).

If you have an other solution (scroll images like pages) for me let met know!

My code:

package nl.ipear.vngmagazine;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;

public class ShowMagazine2 extends FragmentActivity {
    private ViewPager myPager;
    private MyPagerAdapter myPagerAdapter;

    private static int NUM_PAGES = 15;

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

        myPager = (ViewPager)findViewById(R.id.viewpager1);
        myPagerAdapter = new MyPagerAdapter();
        myPager.setAdapter(myPagerAdapter);

        return;
    }

    private class MyPagerAdapter extends PagerAdapter{
        @Override
        public int getCount() {
            return NUM_PAGES;
        }

        @Override
        public Object instantiateItem(View collection, int position) {      
            String location = Environment.getExternalStorageDirectory() + "/MYData/" + "2012-02/";

            // Inflate and create the view
            LayoutInflater layoutInflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View view = layoutInflater.inflate(R.layout.magazinepageview, null);

            ImageView imageView = (ImageView) view.findViewById(R.id.magazinePageImage);
            String fileName = String.format("%s%s%02d%s", location, "2012-02_Page_", position + 1, ".png");
            Log.v("PNG", fileName);
            imageView.setImageBitmap(BitmapFactory.decodeFile(fileName));

            ((ViewPager) collection).addView(view,0);

            return view;
        }

        @Override
        public void destroyItem(View collection, int position, Object view) {
            ((ViewPager) collection).removeView((View) view);           
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view==((View)object);
        }

        @Override
        public void finishUpdate(View arg0) {}

        @Override
        public void restoreState(Parcelable arg0, ClassLoader arg1) {}

        @Override
        public Parcelable saveState() {
            return null;
        }

        @Override
        public void startUpdate(View arg0) {}   
    }
}

解决方案

Yes follow Mimminito. I advice 2 pages since rendering is equally fast for back and forth for 3 pages.

Now if you need the images without lag and the images are on the internet. Make sure you download it and put inside an internalStorageDevice then reuse it if it exist.

my top answer is maybe incorrect for the issue of a memory leak. This new answer is a probable reason for the memory leak is because of the height and width of the image.

private byte[] resizeImage( byte[] input ) {

    if ( input == null ) {
        return null;
    }

    Bitmap bitmapOrg = BitmapFactory.decodeByteArray(input, 0, input.length);

    if ( bitmapOrg == null ) {
        return null;
    }

    int height = bitmapOrg.getHeight();
    int width = bitmapOrg.getWidth();
    int newHeight = 250;

    float scaleHeight = ((float) newHeight) / height;

    // creates matrix for the manipulation
    Matrix matrix = new Matrix();
    // resize the bit map
    matrix.postScale(scaleHeight, scaleHeight);

    // recreate the new Bitmap
    Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
            width, height, matrix, true);

    bitmapOrg.recycle();

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    resizedBitmap.compress(CompressFormat.PNG, 0 /*ignored for PNG*/, bos);            

    resizedBitmap.recycle();

    return bos.toByteArray();            
}       

This top code is for rescalling a bitmap "newHeight" is the new height given to the bitmap.

Now if this doesn't work I am now 100% certain that OP must be overloading the ViewPager with a more views that the android memory can handle. The solution for this is to use a ViewFlipper and use the answer I stated above.