Похоже, что основная проблема, с которой вы столкнулись, заключается не столько в высокой производительности приложения (с чем помогут такие вещи, как буферы фиксированного размера и статическое распределение), но и в общем объеме используемой памяти. Способ контролировать это с помощью виртуализации.
Ленивая загрузка приводит вас на полпути: вы на самом деле не создаете объект, пока что-то не понадобится. Это нормально, но чем дольше пользователь работает с приложением и чем больше объектов он посещает в пользовательском интерфейсе, тем больше объектов создается, и в конечном итоге приложению не хватает памяти.
Итак, вы хотите выбросить объекты, которые больше не нужны пользователю. Выяснить, какие объекты не нужны пользователю, может быть трудной задачей, но это также может быть так же просто, как предположить, что пользователю не нужен объект, который он использовал не так давно. Для этого вы используете наименее недавно использованный (LRU) кеш.
Это полностью соответствует шаблону MVVM. В вашем классе представления вы заставляете свой объект getter для объекта использовать этот псевдокод:
if object hasn't been loaded
load object
add object to the LRU cache (whether you loaded it or not)
return object
Кэш LRU, который я написал , содержит простую очередь объектов, которые он содержит. Когда вы добавляете объект в кеш, если он еще не находится в очереди, он добавляется в конец, а если он уже находится в очереди, он перемещается в конец.
Если при добавлении объекта очередь достигает своей емкости, она выскакивает из того, что находится в начале очереди (то есть того, который использовался не так давно), и вызывает событие DiscardingOldestItem
.
Это событие - это шанс объекта сообщить всему, что содержит ссылку на него (то есть объект представления, к которому он относится), о том, что он должен быть отброшен (возможно, вызвав собственное событие). Обработчик события объекта представления должен сначала вызвать событие PropertyChanged
. Если метод get свойства вызывается, когда он делает это, где-то есть привязка, которая все еще смотрит на свойство, поэтому его пока не следует отбрасывать. (Кроме того, поскольку был вызван метод получения, объект только что был перемещен в конец очереди.) В противном случае его можно выбросить.
(Обратите внимание, что если в интерфейсе пользователя видно больше объектов, чем может вместить кеш, этот маленький танец превращается в бесконечный цикл, и вы получите переполнение стека.)
В более изощренном подходе кэш LRU начал отбрасывать старые элементы, когда у приложения стало мало памяти (сейчас оно использует фиксированную емкость). Это прямое изменение, но если вы сделаете это изменение, то сценарий, описанный в предыдущем абзаце, - это то, о чем вам нужно подумать; один очень большой объект может привести к тому, что весь пользовательский интерфейс станет каблуей.