azerphoenix
@azerphoenix
Java Software Engineer

Как исправить OOM в recyclerview?

Доброго времени суток.
Использую готовое БД sqlite и recyclerview для вывода данных. (Для БД использую SqliteAssetHelper вместо SqliteOpenHelper). А сейчас по существу: при запуске приложения получал NPE, сейчас этот момент исправил, но теперь в MainActivity получаю OOM (out of memory). Честно говоря, не знаю в какую сторону копать, так как описанные в сети случаи OOM в recyclerview связаны с изображениями и с Glide, Picssso и т.д. Проблема возникает при подключении адаптера. Ниже предоставлен код метода Oncreate в MainActivity, адаптера и POD. NPE получал по причине того, что просто забыл создать экземпляр БД. А вот, к чему OOM не пойму...

Метод Oncreate()
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

 db = new DatabaseOpenHelper(this);
//        db.openDatabase();
//        db.getAllData();
//        Log.d(DRUGS_LOG, "Доступ к БД открыт");

        //Log.d(DRUGS_LOG, "T:" + medicationsAdapter.getItemCount());

        //medicationList =  new ArrayList<Medication>();

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        // Подключаем адаптер
        medicationsAdapter = new MedicationsAdapter(db.getAllData(), this);
        recyclerView.setAdapter(medicationsAdapter);

        // Добавляем разделитель для recyclerView
        recyclerView.addItemDecoration(new DividerItemDecoration(
                getApplicationContext()
        ));
    }


Адаптер:
public class MedicationsAdapter extends RecyclerView.Adapter<MedicationsAdapter.MedicationsViewHolder> {

    private static final String DRUGS_LOG = "mylogs";
    private Context mContext;
    private List<Medication> medicationList;

    // Конструктор
    public MedicationsAdapter(List<Medication> medicationsList, Context mContext) {
        this.medicationList = medicationsList;
        this.mContext = mContext;
    }

    public class MedicationsViewHolder extends RecyclerView.ViewHolder {

        public TextView tradeNameText;
        public TextView intNameText;
        public ImageButton imageButton;

        public MedicationsViewHolder(final View itemView) {
            super(itemView);

            tradeNameText = itemView.findViewById(R.id.medication_trade_name);
            intNameText = itemView.findViewById(R.id.medication_int_name);
            imageButton = itemView.findViewById(R.id.favorite_button);

            imageButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Log.d(DRUGS_LOG, "Была нажата кнопка \"Избранное\"");

                }
            });
        }
    }

    @Override
    public MedicationsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.medication_item, parent, false);
        return new MedicationsViewHolder(view);
    }

    @Override
    public void onBindViewHolder(MedicationsViewHolder holder, int position) {

        holder.tradeNameText.setText(medicationList.get(position).get_tradeName());
        holder.intNameText.setText(medicationList.get(position).get_intName());
    }

    @Override
    public int getItemCount() {
        return medicationList.size();
    }
}


POJO -
POJO Medication
public class Medication {
    int _id;
    String _tradeName, _intName, _atc, _description;

    // Конструкторы
    public Medication(int _id, String _tradeName, String _intName, String _atc, String _description) {
        this._id = _id;
        this._tradeName = _tradeName;
        this._intName = _intName;
        this._atc = _atc;
        this._description = _description;
    }
    public Medication() {}
    public Medication(String _tradeName, String _intName) {
        this._tradeName = _tradeName;
        this._intName = _intName;
    }

    // Геттеры
    public int get_id() {
        return _id;
    }

    public String get_tradeName() {
        return _tradeName;
    }

    public String get_intName() {
        return _intName;
    }

    public String get_atc() {
        return _atc;
    }

    public String get_description() {
        return _description;
    }

    // Сеттеры

    public void set_id(int _id) {
        this._id = _id;
    }

    public void set_tradeName(String _tradeName) {
        this._tradeName = _tradeName;
    }

    public void set_intName(String _intName) {
        this._intName = _intName;
    }

    public void set_atc(String _atc) {
        this._atc = _atc;
    }

    public void set_description(String _description) {
        this._description = _description;
    }
}
Лог
05-19 15:46:12.111 30278-30278/info.md7.dermanlar D/dalvikvm: GC_BEFORE_OOM freed <1K, 1% free 98187K/98304K, paused 85ms, total 85ms
05-19 15:46:12.111 30278-30278/info.md7.dermanlar E/dalvikvm-heap: Out of memory on a 24-byte allocation.
05-19 15:46:12.111 30278-30278/info.md7.dermanlar I/dalvikvm: "main" prio=5 tid=1 RUNNABLE
...
...
...
05-19 15:46:12.111 30278-30278/info.md7.dermanlar I/dalvikvm:     at info.md7.sqlite.DatabaseOpenHelper.getAllData(DatabaseOpenHelper.java:144)
05-19 15:46:12.111 30278-30278/info.md7.dermanlar I/dalvikvm:     at info.md7.dermanlar.MainActivity.onCreate(MainActivity.java:52)
....
.....
.....
05-19 15:46:12.247 30278-30278/info.md7.dermanlar D/dalvikvm: GC_BEFORE_OOM freed 0K, 1% free 98187K/98304K, paused 70ms, total 70ms
05-19 15:46:12.247 30278-30278/info.md7.dermanlar E/dalvikvm-heap: Out of memory on a 28-byte allocation.
05-19 15:46:12.247 30278-30278/info.md7.dermanlar I/dalvikvm: "main" prio=5 tid=1 RUNNABLE
....
....
....
05-19 15:46:13.051 30278-30278/info.md7.dermanlar E/AndroidRuntime: FATAL EXCEPTION: main
                                                                    java.lang.OutOfMemoryError: [memory exhausted]
                                                                        at dalvik.system.NativeStart.main(Native Method)
05-19 15:46:13.051 25243-25254/system_process W/ActivityManager:   Force finishing activity info.md7.dermanlar/.MainActivity
05-19 15:46:13.555 25243-25347/system_process I/qtaguid: Failed write_ctrl(s 1 10023) res=-1 errno=1

Подскажете в каком направлении копать? И в чем может заключаться ошибка?
Заранее благодарю за ответы.!
  • Вопрос задан
  • 114 просмотров
Решения вопроса 1
thelongrunsmoke
@thelongrunsmoke
Программист
Судя по всему, вы зачем-то выгружаете в память всё содержимое базы данных. Зачем?
Есть очень простой подход, в onBindViewHolder() достаёте из базы нужную запись и заполняете элемент списка, для этого потребуется только номер элемента в списке который получается как holder.getLayoutPosition().
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы