Страницы

Поиск по вопросам

четверг, 16 мая 2019 г.

Ошибка OutOfMemoryError при работе с изображениями

Делаю приложение, одним из составляющих которого является список, получающий данные для отображения из базы данных. Элемент списка состоит из маленького изображения и текста. В бд хранится текст и uri для получения определенного изображения из папки drawable. При нажатии на элемент списка открывается активити, где, в том числе, показывается то самое определенное изображение. Также имеются ещё пару активити со списками и изображениями и текстовыми данными (всё берется из бд).
Проблема в следующем: по мере открытия новых активити, прокручивании списков, возврата к старым активити постоянно возрастает объём занимаемой приложением ОЗУ, и по достижении определенного момента приложение вылетает, выдавая OutOfMemoryError.
Пробовал получать Cursor через AsyncTask, но на данной ситуации это никак не отразилось. Судя по Java Heap происходит утечка памяти, но не совсем понимаю с чем она связана. Может кто знает как исправить? Заранее благодарю
Далее прилагаю код одного из активити со списком, логи и скрин Java Heap
import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.support.v4.widget.SimpleCursorAdapter; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ListView;

public class MyActivity extends AppCompatActivity {
MyDBHelper myDBHelper; SQLiteDatabase sqLiteDatabase; Cursor cursor; ListView listView; SimpleCursorAdapter simpleCursorAdapter;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list_of__vyzi_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
listView = (ListView) findViewById(R.id.list_of_vyzi); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { Intent intent = new Intent(getApplicationContext(), UniversityMainActivity.class); intent.putExtra("_id", id);
startActivity(intent); } });
// открываем подключение myDBHelper = new MyDBHelper(getApplicationContext()); sqLiteDatabase = myDBHelper.open();
//получаем данные из бд в виде курсора cursor = sqLiteDatabase.query(TablesNames.UNIVERSITIES, new String[] {UniMainInfoConsts.ID, UniMainInfoConsts.IMG_SRC, MyDBHelper.COLUMN_UNI, MyDBHelper.COLUMN_BRI}, null, null,null,null,null);
// определяем, какие столбцы из курсора будут выводиться в ListView cursor.moveToFirst(); String[] headers = new String[] {UniMainInfoConsts.IMG_SRC, MyDBHelper.COLUMN_UNI, MyDBHelper.COLUMN_BRI}; // создаем адаптер, передаем в него курсор simpleCursorAdapter = new SimpleCursorAdapter(this, R.layout.layout_for_list, cursor, headers, new int[]{R.id.imageView, R.id.main_text, R.id.sub_text}, 0);
listView.setAdapter(simpleCursorAdapter); }
@Override public void onDestroy(){ super.onDestroy(); // Закрываем подключение и курсор sqLiteDatabase.close(); cursor.close(); myDBHelper.close(); Log.d("Destr", "List destr"); }
public void openAddComment (View v){ Intent intent = new Intent(this, Add_comment_activity.class); startActivity(intent); }

}
Java Heap

04-28 22:22:35.744 5511-5511/ru.abityrienty.vyzi I/Choreographer: Skipped 30 frames! The application may be doing too much work on its main thread. 04-28 22:22:37.365 5511-5511/ru.abityrienty.vyzi I/PersonaManager: getPersonaService() name persona_policy 04-28 22:22:37.445 5511-5511/ru.abityrienty.vyzi D/AbsListView: Get MotionRecognitionManager 04-28 22:22:38.877 5511-5511/ru.abityrienty.vyzi D/DESTROY: InstPage has destroyed 04-28 22:22:38.877 5511-5511/ru.abityrienty.vyzi D/AbsListView: onDetachedFromWindow 04-28 22:22:39.558 5511-5511/ru.abityrienty.vyzi D/AbsListView: Get MotionRecognitionManager 04-28 22:22:39.598 5511-5511/ru.abityrienty.vyzi I/PersonaManager: getPersonaService() name persona_policy 04-28 22:22:40.218 5511-5511/ru.abityrienty.vyzi D/DESTROY: InstPage has destroyed 04-28 22:22:40.228 5511-5511/ru.abityrienty.vyzi D/AbsListView: onDetachedFromWindow 04-28 22:22:41.249 5511-5511/ru.abityrienty.vyzi D/dalvikvm: GC_FOR_ALLOC freed 17393K, 23% free 60720K/78840K, paused 22ms, total 26ms 04-28 22:22:41.370 5511-5511/ru.abityrienty.vyzi D/dalvikvm: GC_FOR_ALLOC freed 7174K, 31% free 55185K/78840K, paused 20ms, total 20ms 04-28 22:22:41.530 5511-5511/ru.abityrienty.vyzi I/dalvikvm-heap: Grow heap (frag case) to 74.282MB for 18662416-byte allocation freed 17393K, 23% free 60720K/78840K, paused 22ms, total 26ms 04-28 22:22:41.370 5511-5511/ru.abityrienty.vyzi D/dalvikvm: GC_FOR_ALLOC freed 7174K, 31% free 55185K/78840K, paused 20ms, total 20ms 04-28 22:22:41.530 5511-5511/ru.abityrienty.vyzi I/dalvikvm-heap: Grow heap (frag case) to 74.282MB for 18662416-byte allocation 04-28 22:22:42.791 5511-5511/ru.abityrienty.vyzi D/dalvikvm: GC_FOR_ALLOC freed 25168K, 23% free 61188K/78828K, paused 38ms, total 38ms 04-28 22:22:42.811 5511-5511/ru.abityrienty.vyzi I/dalvikvm-heap: Grow heap (frag case) to 69.961MB for 7985680-byte allocation 04-28 22:22:42.951 5511-5511/ru.abityrienty.vyzi D/dalvikvm: GC_FOR_ALLOC freed 3595K, 23% free 66797K/86628K, paused 19ms, total 19ms 04-28 22:22:44.683 5511-5511/ru.abityrienty.vyzi I/dalvikvm-heap: Forcing collection of SoftReferences for 18662416-byte allocation 04-28 22:22:44.723 5511-5511/ru.abityrienty.vyzi D/dalvikvm: GC_BEFORE_OOM freed 23183K, 26% free 54168K/73080K, paused 37ms, total 38ms 04-28 22:22:46.105 5511-5511/ru.abityrienty.vyzi D/AbsListView: Get MotionRecognitionManager 04-28 22:22:46.135 5511-5511/ru.abityrienty.vyzi I/PersonaManager: getPersonaService() name persona_policy 04-28 22:22:47.516 5511-5511/ru.abityrienty.vyzi D/DESTROY: InstPage has destroyed 04-28 22:22:47.516 5511-5511/ru.abityrienty.vyzi D/AbsListView: onDetachedFromWindow 04-28 22:22:48.597 5511-5511/ru.abityrienty.vyzi D/dalvikvm: GC_FOR_ALLOC freed 19896K, 9% free 66731K/73080K, paused 25ms, total 26ms 04-28 22:22:48.617 5511-5511/ru.abityrienty.vyzi I/dalvikvm-heap: Grow heap (frag case) to 75.380MB for 7985680-byte allocation 04-28 22:22:48.687 5511-5511/ru.abityrienty.vyzi D/dalvikvm: GC_FOR_ALLOC freed 1165K, 8% free 74770K/80880K, paused 19ms, total 19ms 04-28 22:22:49.518 5511-5511/ru.abityrienty.vyzi I/dalvikvm-heap: Forcing collection of SoftReferences for 18662416-byte allocation 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi D/dalvikvm: GC_BEFORE_OOM freed 25070K, 32% free 59775K/87240K, paused 24ms, total 25ms 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi E/dalvikvm-heap: Out of memory on a 18662416-byte allocation. 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi I/dalvikvm: "main" prio=5 tid=1 RUNNABLE 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi I/dalvikvm: | group="main" sCount=0 dsCount=0 obj=0x41855ea0 self=0x4174b050 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi I/dalvikvm: | sysTid=5511 nice=0 sched=0/0 cgrp=apps handle=1073848660 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi I/dalvikvm: | state=R schedstat=( 0 0 0 ) utm=532 stm=230 core=0 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:693) 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:518) 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:889) 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.content.res.Resources.loadDrawable(Resources.java:3457) 04-28 22:22:49.548 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.content.res.Resources.getDrawable(Resources.java:1921) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.widget.ImageView.resolveUri(ImageView.java:666) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.widget.ImageView.setImageURI(ImageView.java:409) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.support.v4.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:201) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.support.v4.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:147) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.support.v4.widget.CursorAdapter.getView(CursorAdapter.java:273) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.widget.AbsListView.obtainView(AbsListView.java:2713) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.widget.ListView.makeAndAddView(ListView.java:1811) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.widget.ListView.fillDown(ListView.java:697) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.widget.ListView.fillGap(ListView.java:661) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.widget.AbsListView.trackMotionScroll(AbsListView.java:6693) 04-28 22:22:49.558 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:5692) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.view.Choreographer$CallbackRecord.run(Choreographer.java:813) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.view.Choreographer.doCallbacks(Choreographer.java:613) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.view.Choreographer.doFrame(Choreographer.java:582) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:799) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.os.Handler.handleCallback(Handler.java:733) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.os.Handler.dispatchMessage(Handler.java:95) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.os.Looper.loop(Looper.java:146) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at android.app.ActivityThread.main(ActivityThread.java:5593) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at java.lang.reflect.Method.invokeNative(Native Method) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at java.lang.reflect.Method.invoke(Method.java:515) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi I/dalvikvm: at dalvik.system.NativeStart.main(Native Method) 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi D/skia: --- allocation failed for scaled bitmap 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi D/AndroidRuntime: Shutting down VM 04-28 22:22:49.568 5511-5511/ru.abityrienty.vyzi W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41854da0) 04-28 22:22:49.578 5511-5511/ru.abityrienty.vyzi E/AndroidRuntime: FATAL EXCEPTION: main Process: ru.abityrienty.vyzi, PID: 5511 java.lang.OutOfMemoryError at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:693) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:518) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:889) at android.content.res.Resources.loadDrawable(Resources.java:3457) at android.content.res.Resources.getDrawable(Resources.java:1921) at android.widget.ImageView.resolveUri(ImageView.java:666) at android.widget.ImageView.setImageURI(ImageView.java:409) at android.support.v4.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:201) at android.support.v4.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:147) at android.support.v4.widget.CursorAdapter.getView(CursorAdapter.java:273) at android.widget.AbsListView.obtainView(AbsListView.java:2713) at android.widget.ListView.makeAndAddView(ListView.java:1811) at android.widget.ListView.fillDown(ListView.java:697) at android.widget.ListView.fillGap(ListView.java:661) at android.widget.AbsListView.trackMotionScroll(AbsListView.java:6693) at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:5692) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:813) at android.view.Choreographer.doCallbacks(Choreographer.java:613) at android.view.Choreographer.doFrame(Choreographer.java:582) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:799) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:146) at android.app.ActivityThread.main(ActivityThread.java:5593) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099) at dalvik.system.NativeStart.main(Native Method)
Натыкался вот на такое, но не совсем понял как воплотить в жизнь:
The real solution involves:
Ensuring that you have profiled your app's allocations and are not leaking memory Ensuring that you have profiled your app's allocations and are not leaking memory You are not holding references to Bitmaps via a hidden or non-displayed Fragment, View, etc.. in such a way that they can not be collected and released You are using a Bitmap cache (i.e. LruCache) to manage how many Bitmaps are been held in memory at any give time That the Bitmaps that are actually being held in memory are sized appropriately for the device's resolution, i.e.: Resizing content on the device on the fly and file caching the results Dynamically via the web service that you are requesting them from
Переделанный адаптер для получения BLOB
import android.content.Context; import android.content.res.Resources; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.support.v4.widget.SimpleCursorAdapter; import android.widget.ImageView;
public class ListOfVyziAdapter extends SimpleCursorAdapter {
/** * It's important to place column where you store images on the first place * of the @from array */
Context ctx; // String [] columns = {0="img_src",1="for main_text", 2="for sub_text"} String [] columns;
public ListOfVyziAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); ctx = context; columns = from; }
@Override public void setViewImage(ImageView v, String value) {
v.setImageDrawable(imageForList(getCursor())); }
private Drawable imageForList(Cursor cur){
byte [] blob = cur.getBlob(cur.getColumnIndex(columns[0])); Bitmap bitmap = BitmapFactory.decodeByteArray(blob, 0, blob.length); return new BitmapDrawable(Resources.getSystem(), bitmap); } }


Ответ

Для того чтоб бороться с OOM вначале вам необходимо создать такую возможность.
Определите свой адаптер, иначе вам очень сложно(невозможно) контролировать процесс биндинга(bind) Blob из Sql в ImageView, а так у вас появится возможность контролировать размер изображения, применить компрессию, сделать кеширование, и самое главное учесть возможность выделения памяти для разных устройств. Для простоты можно использовать готовые решения, которые уже зарекомендовали себя например Glide там будет проще сделать, в Picasso не поддерживается load для byte[] или Bitmap, только Drawable и Url.

Комментариев нет:

Отправить комментарий