Как правильно организовать хранение объектов в Android приложении?
====================================================================

 Здравствуйте!  
  

Пишу небольшое приложение под Андроид — простенький органайзер  

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

Не могу решить, как лучше организовать их хранение.  

Можно сделать таблицу в базе данных для них, где будут соответствующие поля "время", "дата", "текст", "путь к файлу" (Тогда отслеживать, что он остался прежним).  

Но мне кажется, что такой подход не совсем верный, ведь напоминания — это объекты, с которыми удобно было бы работать, непосредственно обращаясь к ним, вызывая методы, например, *note1.delete()*.  

Как решить эту задачу с помощью объектов я не представляю. Допустим, в приложении мы создали таких несколько, но как быть дальше? Надо их где-то хранить. В той же базе данных? Тогда при запуске потребуется их вновь инициализировать. Или этот процесс не так страшен? Но в таком случае достаточно написать методы, которые работают с таблицей так же, как работали бы с объектами, но с той лишь разницей, что им в качестве аргумента передаём ещё id строчки в таблице, которая будет "псевдообъектом", например, *deleteNote(1)*.  
  

Как же сделать лучше? Может, есть другие подходы? 

 Во-первых, судя по вашему описанию предметной области задачи (всего один тип объектов, фиксированный набор атрибутов объекта), база данных – то, что вам нужно. Не надо бояться инициализации объектов, потому что способа избежать восстановления объекта из хранилища (какое бы оно ни было) в данном случае нет: храните в базе – придётся инициализировать объект значениями столбцов таблицы; храните, скажем, в JSON – придётся инициализировать объект значениями, полученными из JSON-объекта (что, кстати, ещё менее удобно); используете Java-сериализацию – и там тоже будут накладные расходы на восстановление объекта из формата, в котором вы его сохранили, ну и так далее. А БД – очень удобный формат. К тому же, никто вас не заставляет инициализировать все-все объекты на старте программы: если у пользователя очень много заметок, то можно просто подгружать новые по мере листания списка.  

Во-вторых, по поводу 
> напоминания — это объекты, с которыми удобно было бы работать, непосредственно обращаясь к ним, вызывая методы

  

Есть такая вещь, как [single responsibility principle](http://en.wikipedia.org/wiki/Single_responsibility_principle) (и [то же самое на русском](https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF_%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9_%D0%BE%D0%B1%D1%8F%D0%B7%D0%B0%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8)), суть которой вкратце состоит в том, что класс должен выполнять только конкретный ограниченный круг обязанностей, и больше ничего. В данном случае ваша ошибка в том, что вы думаете о том, чтобы дать классу заметки обязанности, которые ему по идее не свойственны. Заметка в данном случае – просто сущность, отображающая хранимые данные, больше ничего, и она ничего не должна знать об уровне хранения и т.п. Так что методов типа delete(), save() и подобных у неё точно не должно быть. А вам для удобства хранения и загрузки объектов я предлагаю сделать отдельный класс типа такого (написано на коленке просто чтобы передать идею):  

```
public class NotesManager {
       private final SQLiteDatabase db;

       public NotesManager(SQLiteDatabase db) { this.db = db; }

       public Note findById(int noteId) {
              Cursor c = db.query(...);
              //тут чтение в локальные переменные значений
              //отдельных полей из курсора,
              //если он вернул какой-то результат
              return new Note(...ранее считанные значения полей как аргументы конструктора...);
       }

       public void save(...перечисление полей...) {
              //после проверки введённых данных делаете 
              //insert в базу с переданными значениями полей 
       }
}
```
  

Также вам понадобятся методы create и delete, но если вы поняли идею, то наверняка справитесь :) Задавайте ещё вопросы, если что-то непонятно. 

> Можно сделать таблицу в базе данных для них, где будут соответствующие поля "время", "дата", "текст", "путь к файлу" (Тогда отслеживать, что он остался прежним).  
> 
> Но мне кажется, что такой подход не совсем верный, ведь напоминания — это объекты, с которыми удобно было бы работать, непосредственно обращаясь к ним, вызывая методы, например, note1.delete().  
> 
> Как решить эту задачу с помощью объектов я не представляю. Допустим, в приложении мы создали таких несколько, но как быть дальше? Надо их где-то хранить. В той же базе данных? 

  
  

Если вам удобно (да так в принципе и правильно, хотя и медленнее) работать с объектами а не с записями в БД - то **для таких вещей есть такая штука как [ORM](https://ru.wikipedia.org/wiki/ORM).** (*у вас конечно простой случай, и потому работать с записями в вашем проекте - самое то. И тем более - если вы новичок - стоит разобраться с тем, как работать с БД напрямую. Но вообще, как только сделаете учебный проект с БД - , стоит понять, что в других сложных проектах - проблем с БД будет гораздо больше и будет сложнее и лучше осваиваться с "промышленными подходами"*)  
  

В общем есть ORM. Если расшифровывать - это "модель/правила" которая/которые позволяют вам сохранять состояния объектов в БД и восстанавливать их.   

А на практике - это набор классом которые делают за вас всю черновую работу по взаимодействию с БД (или тем хранилищем которое под ними лежит). И вы работаете не с БД, а с некой абстракцией, которая скрывает от вас что где и как она хранит в БД или том хранилище, которая ORM использует.   
  

Т.е. вы говорите что-то типа - "*О, мой ORM! дай мне объект типа 'МояЗаметка' c идентификатором 12345!*" и он сам лезет куда-то в БД (куда именно - это его личные проблемы) и отдает вам обхект класса МояЗаметка которая заполнена данными заметки с номером 12345. А дальше - "чо хошь с ним, то и делай".   
  

А как сделал все что надо (дургая его методы, меняя свойства или как ещё), - отдаешь его обратно своему ORM-слою ( ORM можно рассматривать как слой абстракции над БД или любым другим хранилищем ) - типа "*на вот тебе объект, сохрани его в БД.*" - и механизмы ORM делают всю черновую работу по генерации SQL-запросов и всего прочего за вас.  
  

В зависимости от того что от орм хотели создатели, ORM может или нет управлять структурой БД или пытаться вытаскивать свои объекты из ранее созданной структуры; управлять метаданными ваших объектов и (например) содержать или нет данные о том, как эти свойства надо отображать или нет.  
  

В некоторых ORM есть кодогенератор - т.е. вы даете ему описания классов, а он вам генерирует код, который сохраняет классы в БД и восстанавливает оттуда. Часть ORM-механизмов работтают отталкиваясь от аннотаций - т.е. вы над каждым из полей которые хотите сохранять в БД надписываете его имя, тип, индексацию и другие параметры - так например делает [Persistence API](https://ru.wikipedia.org/wiki/Java_Persistence_API) - но его нет на Андроиде, потому это не наш случай (да и работа через рефлекшен считается медленной).  
  

Ещё могу дать 2 ссылки - на сравнительную статью ОРМ для Андроид и на мой сосбвтенный ОРМ-велосипед :   

[www.ninthavenue.com.au/android-orm-jpa](http://www.ninthavenue.com.au/android-orm-jpa)  

[https://gitorious.org/unat/pages/SimpleORM\_Overvie...](https://gitorious.org/unat/pages/SimpleORM_Overview.markdown)  

(*последнее - "на правах рекламы". творение моё, но давно не обновлявшееся в публичной репе. Сейчас много изменений, как сдаим текущий проект - опубликую что поновее. В принципе, не столько для пользования, сколько вам - для освоения идей и выдачи конструктивной критики и вопросов. если что - спрашивайте - по UnAT я вам расскажу всё))*) 

 Не плохой вариант посмотреть в сторону [CouchbaseLite](http://www.couchbase.com/nosql-databases/couchbase-mobile)