如何与And​​roid的ImageView的内存分配工作? [英] How does Android memory allocation work with ImageView?

查看:193
本文介绍了如何与And​​roid的ImageView的内存分配工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是从服务器上传约20大小50-70K的照片,然后在的ListView 显示它们。我最初存储的数据为位图这会导致内存很快用尽。然后,我决定把玉米preSS所有这些位图文件,并存储在内容提供商新闻。所以在我的转接器,用户数据只包含乌里来的图像文件。

但它并没有解决问题的话,那运行时间长一点,但装载约10张照片左右后,仍然坠毁。以下是编译器错误日志。结果
1048576字节外部分配太大,这一进程结果
VM不会让我们分配1048576字节

我甚至将其设置为的ImageView ,以及删除所有图像文件清理干净后每个位图数据它们存储在我的 SD卡

  @覆盖
    公共无效的onDestroy(){
        // 清理
        对于(用户用户:用户列表){
            getContentResolver()删除(user.getImageUri(),NULL,NULL);
        }
        super.onDestroy();
    }
    私人乌里constructUriFromBitmap(位图位图){
        ContentValues​​值=新ContentValues​​(1);
        values​​.put(Media.MIME_TYPE,图像/ JPEG);
        。URI URI = getContentResolver()插入(Media.EXTERNAL_CONTENT_URI,价值观);
        尝试{
            的OutputStream outStream = getContentResolver()openOutputStream(URI)。
            bitmap.com preSS(Bitmap.Com pressFormat.JPEG,50,outStream);
            outStream.close();
        }
        赶上(例外五){
            Log.e(TAG,异常而写入图像,E);
        }
        bitmap.recycle();
        返回URI的;
    }

现在我跑出去的想法,我真的不知道有什么可以在这种情况下出问题。我不知道是否有人已经遇到此问题可以摆脱我一些灯?

由于code是相当长,我只提取主要功能:
这里是我的 User类数据:

 公共类的FriendFeed {
    //所需的参数
    私人最终诠释activityId; //情况下,我们要处理的细节
                                    //这个活动
    私人最终诠释friendId;
    私人最终字符串FRIENDNAME;
    私人最终Challenge.Type challengeType;
    私人最终字符串activityTime;
    私人最终字符串地名;    //可选参数
    私人字符串challengeName;
    私人字符串challengeDescription;
    私人乌里activitySnapPictureUri = NULL;
    私人乌里friendPictureUri = NULL;
    私人字符串activityComment;

这是我的主要功能:

  @覆盖
保护布尔doInBackground(虚空......空隙){
            JSONArray阵列= JsonHelper.getJsonArrayFromUrlWithData(GET_FRIEND_FEED_URL,DATAS);
            如果(阵!= NULL){
                尝试{
                    的for(int i = 0; I< array.length(); ++ I){
                        乌里snapPictureUri = NULL;
                        乌里userPictureUri = NULL;                        如果(Challenge.returnType(array.getJSONObject㈠.getString(challenges_tbl_type))== Challenge.Type.SNAP_PICTURE){
                            snapPictureUri = constructUriFromBitmap(ImageHelper.downloadImage(array.getJSONObject(i).getString(\"activity_tbl_snap_picture_url\")));
                        }                        如果(ImageHelper.downloadImage(array.getJSONObject(I).getString(users_tbl_user_image_url))!= NULL){
                            userPictureUri = constructUriFromBitmap(ImageHelper.downloadImage(array.getJSONObject(i).getString(\"users_tbl_user_image_url\")));
                        }                        publishProgress(
                            新FriendFeed.Builder(
                                    //所需的参数
                                    array.getJSONObject(ⅰ).getInt(activity_tbl_id),
                                    array.getJSONObject(ⅰ).getInt(friends_tbl_friend_id),
                                    array.getJSONObject(ⅰ).getString(users_tbl_username),
                                    Challenge.returnType(array.getJSONObject㈠.getString(challenges_tbl_type)),
                                    array.getJSONObject(ⅰ).getString(activity_tbl_created),
                                    array.getJSONObject(ⅰ).getString(spots_tbl_name))
                                        //可选参数
                                        .challengeName(array.getJSONObject㈠.getString(challenges_tbl_name))
                                        .challengeDescription(array.getJSONObject㈠.getString(challenges_tbl_description))
                                        .activitySnapPictureUri(snapPictureUri)
                                        .friendPictureUri(userPictureUri)
                                        .activityComment(array.getJSONObject㈠.getString(activity_tbl_comment))
                                            。建立());
                    }
                }
                赶上(JSONException E){
                    Log.e(TAG +GetFriendFeedTask.doInBackGround(虚空......空隙):,JSON解析错误数据+ e.toString());
                }
                返回true;
            }
            其他{
                返回false;
            }
        }


解决方案

Android的强制24MB的每个进程的内存分配限制,所以你不能分配不止于此。然而,每个70K 20图片应达到1.4MB只...所以我的猜测:


  1. 也许你分配在你的应用程序的其他部分的位图,所以有不到这个ListView控件可用于您的位图1.4MB。


  2. 内存泄漏的地方


  3. 如果你确定你真的需要您使用的所有位图,你确定你需要的位图是这个大或有这么多的分辨率是多少?减少他们可以提供帮助。


如果一切都失败了,你确实需要大量的位图在内存中,你总是可以使用OpenGL纹理。

I'm loading approximately 20 pictures of size 50-70K from server, then display them in a ListView. Initially I stored the data as Bitmap which causes memory running out quickly. Then I decided to compress all these bitmap files and store in Content provider Media. So in my adapter, the user data only contains the Uri to the image file.

However it didn't fix the problem at all, it run a bit longer, but still crashed after loading about 10 pictures or so. Here is the error log from the compiler.
1048576-byte external allocation too large for this process
VM won't let us allocate 1048576 bytes

I even clean up each bitmap data after setting it to my ImageView, plus delete the all the image files which are stored in my sdcard

    @Override
    public void onDestroy() {
        // clean up
        for (User user : userList) {
            getContentResolver().delete(user.getImageUri(), null, null);
        }
        super.onDestroy();
    }


    private Uri constructUriFromBitmap(Bitmap bitmap) {
        ContentValues values = new ContentValues(1);
        values.put(Media.MIME_TYPE, "image/jpeg");
        Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
        try {
            OutputStream outStream = getContentResolver().openOutputStream(uri);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, outStream);
            outStream.close();
        } 
        catch (Exception e) {
            Log.e(TAG, "exception while writing image", e);
        }
        bitmap.recycle();
        return uri;
    }

Now I ran out of idea, I really don't know what could go wrong in this case. I wonder if anyone has experienced this issue could shed me some lights?

Since the code is quite long, I only extract the main functions: Here is my User class data:

public class FriendFeed {
    // required parameters
    private final int activityId; // in case we want to handle the detail of
                                    // this activity
    private final int friendId;
    private final String friendName;
    private final Challenge.Type challengeType;
    private final String activityTime;
    private final String placeName;

    // optional parameter
    private String challengeName;
    private String challengeDescription;
    private Uri activitySnapPictureUri = null;
    private Uri friendPictureUri = null;
    private String activityComment;

And here is my main function:

@Override
protected Boolean doInBackground(Void...voids) {
            JSONArray array = JsonHelper.getJsonArrayFromUrlWithData(GET_FRIEND_FEED_URL, datas);
            if (array != null) { 
                try {
                    for (int i = 0; i < array.length(); ++i) { 
                        Uri snapPictureUri = null;
                        Uri userPictureUri = null;

                        if (Challenge.returnType(array.getJSONObject(i).getString("challenges_tbl_type")) == Challenge.Type.SNAP_PICTURE) {
                            snapPictureUri = constructUriFromBitmap(ImageHelper.downloadImage(array.getJSONObject(i).getString("activity_tbl_snap_picture_url")));
                        }

                        if(ImageHelper.downloadImage(array.getJSONObject(i).getString("users_tbl_user_image_url")) != null) {
                            userPictureUri = constructUriFromBitmap(ImageHelper.downloadImage(array.getJSONObject(i).getString("users_tbl_user_image_url")));
                        }

                        publishProgress(
                            new FriendFeed.Builder(
                                    // required parameters
                                    array.getJSONObject(i).getInt("activity_tbl_id"),
                                    array.getJSONObject(i).getInt("friends_tbl_friend_id"),
                                    array.getJSONObject(i).getString("users_tbl_username"),
                                    Challenge.returnType(array.getJSONObject(i).getString("challenges_tbl_type")),
                                    array.getJSONObject(i).getString("activity_tbl_created"),
                                    array.getJSONObject(i).getString("spots_tbl_name"))
                                        // optional parameters
                                        .challengeName(array.getJSONObject(i).getString("challenges_tbl_name"))
                                        .challengeDescription(array.getJSONObject(i).getString("challenges_tbl_description"))
                                        .activitySnapPictureUri(snapPictureUri)
                                        .friendPictureUri(userPictureUri)
                                        .activityComment(array.getJSONObject(i).getString("activity_tbl_comment"))
                                            .build());
                    }
                }
                catch (JSONException e) {
                    Log.e(TAG + "GetFriendFeedTask.doInBackGround(Void ...voids) : ", "JSON error parsing data" + e.toString());
                }
                return true;
            }
            else {
                return false;
            }
        }

解决方案

Android enforces a per-process memory allocation limit of 24MB so you can't allocate more than that. However, 20 pics of 70K each should amount to 1.4MB only... so my guesses:

  1. Maybe you're allocating Bitmaps in other parts of your app, so that there's less than 1.4MB available for your bitmaps on this ListView.

  2. Memory leak somewhere

  3. If you determine that you really need all the bitmaps you're using, are you sure you need the bitmaps to be this large or have this much resolution? Reducing them can help.

If all else fails and you do need lots of bitmaps in memory, you can always use OpenGL textures.

这篇关于如何与And​​roid的ImageView的内存分配工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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