将100个以上的字符串转换为字节数组时发生java.lang.OutOfMemoryError [英] java.lang.OutOfMemoryError while converting over 100 Strings into to byte arrays

查看:160
本文介绍了将100个以上的字符串转换为字节数组时发生java.lang.OutOfMemoryError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我了解关于java.lang.OutOfMemoryError的问题,并且位图已经被问过无数次了.我还检查了有效显示位图页面.

Firstly, I understand questions regarding java.lang.OutOfMemoryError and Bitmaps have already been asked numerous times before. I have also checked out the Displaying Bitmaps Efficiently page.

我的用例:

我将两个不同大小的位图作为字符串存储在SQLite数据库中.位图的第一个大小是屏幕宽度的50%,第二个大小是屏幕宽度的100%.

I am storing two different sized Bitmaps as Strings in an SQLite database. The first size of the Bitmaps is 50% of the screen width, and the second size is 100% of the screen width.

我正在使用一个RecyclerView,该图像在ImageViews中显示的图像是屏幕宽度的50%或100%,因此要加载的位图不会比需要的大,并且在调整大小之前从数据库中检索图像.

I am using a RecyclerView which displays the images in ImageViews which are either 50% or 100% of the screen width, so the Bitmaps being loaded are no bigger than they need to be, and they are appropriately sized before the images are retrieved from the Database.

我也在使用AsyncTask加载位图.

I am also loading the Bitmaps using an AsyncTask.

我在RecyclerView中有180多个不同的项,因此我总共创建了360多个位图(即numberOfimages * theDifferentSizesOfEachImage).我通过以下代码将图像的字符串版本覆盖为字节数组:byte [] byteArray = Base64.decode(encodedString, Base64.DEFAULT);

I have over 180 different items in the RecyclerView so I have a total of over 360 Bitmaps (i.e. numberOfimages * theDifferentSizesOfEachImage) being created. I am coverting the String versions of the images into byte arrays via this code: byte [] byteArray = Base64.decode(encodedString, Base64.DEFAULT);

问题

除非能够重新启动相同的活动(例如,加载活动,然后通过在导航抽屉中再次单击它来重新创建活动),否则活动可以加载大约170张不同的图像而不会出现java.lang.OutOfMemoryError过程),并在将字符串转换为字节数组时产生了java.lang.OutOfMemoryError.

The Activity was able to load over around 170 different images without encurring the java.lang.OutOfMemoryError, unless I restarted the same Activity (e.g. load the Activity, then recreate the Activity by clicking on it again in the Navigation Drawer and then repeating that process) and incurred the java.lang.OutOfMemoryError whilst converting the Strings into byte arrays.

我正在使用 Glide 库并使用以下代码将字节数组转换为位图:

I am converting the byte array to a Bitmap using the Glide library using the following code:

 Bitmap bitmap = Glide.with(context).load(byteArray).asBitmap()
 .dontTransform().dontAnimate().skipMemoryCache(true)
 .diskCacheStrategy(DiskCacheStrategy.NONE).into(-1, -1).get();

我的问题简而言之

在将字符串转换为字节数组时,如何避免出现java.lang.OutOfMemoryError?

How do I avoid the java.lang.OutOfMemoryError occurring whilst am I converting the Strings into byte arrays?

注意

使用Glide创建位图后,我在给定的位图上调用recycle(),然后将其设置为null.

After creating a Bitmap using Glide I am calling recycle() on the given Bitmap and then setting it to null.

我也已经在Android Manifest中使用android:largeHeap="true"

I am also already using android:largeHeap="true" in my Android Manifest

预先感谢

修改

这是我创建位图字符串的方式:

Here is how I am creating the Bitmap Strings:

 ByteArrayOutputStream baos = new  ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.WEBP,100, baos);
        byte [] b =baos.toByteArray();
     String bitmapString = Base64.encodeToString(b, Base64.DEFAULT);

推荐答案

我建议您放弃的方法,这将不适用于大量图像,并且您已经在线程上进行了大量工作来处理.永远不要在sqllite中存储像这样的图像. 您只需将位图转换为具有唯一名称或可以相同(取决于您的用例)的文件,然后就可以将该文件保存在应用程序目录中,并将文件路径保存在数据库中.这里有一些代码可以帮助您.

What i would suggest you to drop your approach, this would just not work with large set of image and you are already putting to much work on your thread to handle. One should never store image like that in the sqllite. You should just convert your bitmap to a file having unique name or could be same (depends upon your use case) then you can just save this file inside the app directory and save the file path in database. Here is some code to help you.

File pictureFile = getOutputMediaFile(getActivity(), MEDIA_TYPE_IMAGE);
        if (pictureFile == null) {
            return;
        }
        Bitmap bitmap =BitmapFactory.decodeByteArray(data,0,data.length);

            FileOutputStream fos = new FileOutputStream(pictureFile);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();

私有文件getOutputMediaFile(Context context,int m){

private File getOutputMediaFile(Context context, int m) {

    File mediaStorageDir = context.getFilesDir();

    if (!mediaStorageDir.exists()) {
        if (!mediaStorageDir.mkdirs()) {
            Log.d("Fade", "failed to create directory");
            return null;
        }
    }
    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
            .format(new Date());

    File mediaFile=new File(mediaStorageDir.getPath()+File.separator
                + "IMG_" + timeStamp + ".JPG");

    return mediaFile;
}

现在您已经有了文件,现在您可以将文件路径存储在数据库中,并且在需要时始终可以使用glide从存储中获取文件.这也将使您的数据库快速查询.

Now you have the file and now you can just store the file path in the database and when its needed you can always get your file from the storage using glide. This would also make your database fast to queries.

这样,您就不需要在gradle或其他任何地方进行任何更改.试试这个.

This way you wont need any changes in gradle or anywhere else. Try this.

这篇关于将100个以上的字符串转换为字节数组时发生java.lang.OutOfMemoryError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆