Я загружаю приблизительно 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;
}
}