Как распределение памяти Android работает с ImageView? - PullRequest
2 голосов
/ 06 января 2012

Я загружаю приблизительно 20 изображений размером 50-70К с сервера, затем отображаю их в виде ListView.Первоначально я сохранил данные как Bitmap, что приводит к быстрому исчерпанию памяти.Затем я решил сжать все эти растровые файлы и сохранить их в контент-провайдере Media.Так что в моем адаптере пользовательские данные содержат только Uri к файлу изображения.

Однако это не решило проблему совсем, оно работало немного дольше, но все равно зависало после загрузки около 10 изображений или около того.Вот журнал ошибок от компилятора.
1048576-byte external allocation too large for this process
VM won't let us allocate 1048576 bytes

Я даже очищаю все bitmap данные после установки их в ImageView, плюс удаляю всефайлы изображений, которые хранятся в моем 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;
    }

Теперь у меня закончились идеи, я действительно не знаю, что может пойти не так в этом случае.Интересно, кто-нибудь сталкивался с этой проблемой, мог бы пролить мне свет?

Поскольку код довольно длинный, я извлекаю только основные функции: Вот мои User class данные:

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;

А вот моя основная функция:

@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;
            }
        }

1 Ответ

1 голос
/ 06 января 2012

Android применяет ограничение на выделение памяти для каждого процесса в 24 МБ, поэтому вы не можете выделить больше этого. Тем не менее, 20 фото по 70К каждая должны составлять всего 1,4 МБ ... так что мои предположения:

  1. Возможно, вы размещаете растровые изображения в других частях вашего приложения, поэтому для этого растрового изображения в этом ListView доступно менее 1,4 МБ.

  2. Утечка памяти где-то

  3. Если вы решите, что вам действительно нужны все растровые изображения, которые вы используете, уверены ли вы, что растровые изображения должны быть такими большими или иметь такое большое разрешение? Сокращение их может помочь.

Если все остальное терпит неудачу и вам нужно много растровых изображений в памяти, вы всегда можете использовать текстуры OpenGL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...