Если вы делате что-то сверх тривиального Hello World, то обеспечить "моментальную", без всяких тормозов реакцию интерфейса на действия пользователя дело не такое тривиальное, как это может показаться. Рассмотрим это на примере из простого графического редактора, который я сейчас разрабатываю.
Встроенного механизма для хранения всех операций рисования нет, при каждом вызове процедуры рисования мы должны нарисовать всю картинку. Первый, логичный шаг - сделать класс DrawOperation, хранить все экземпляры в упорядоченном списке и в процедуре рисования быстренько по этому списку пробежаться и все нарисовать. При этом заодно элементарно решается выполнение undo: удалили последний элемент из списка и привет. В каждом экземпляре DrawOperation хранится траектория движения "кисти", вид кисти, цвет, размер и т.п. Очень удобно и логично.
Проблема лишь в том, что "быстренько" не выйдет. Уже после нескольких мазков нашей виртуальной кистью отрисовка начинает заметно притормаживать.
Шаг второй, не менее логичный. Заводим виртуальный холст (Bitmap+Canvas), на котором и будем выполнять само рисование, а затем просто выводить его поверх заранее подготовленного фона. А список операций будем вести параллельно, он нам таки пригодится для undo.
Замечу (но разъяснять не стану, поверьте - он понадобится), что в действительности придется завести еще один виртуальный холст, для текущей операции. По завершении они объединяются, а в процессе накладываются по очереди.
Все замечательно, но все равно притормаживает, а undo выполняется вообще неимоверно долго.
Шаг третий, вместо списка операций храним список "снимков" экрана. Сжатие в PNG позволяет нам хранить довольно большое их количество, делаем это во вспомогательном потоке с меньшим приоритетом, запускаем его когда текущая операция завершается и возникает естественная пауза, пока пользователь не ведет стилусом (пальцем, языком или чем там еще) по экрану, а переставляет его на новое место.
Undo вписалось в приемлемые рамки, теперь мы просто достаем предпоследний снимок, а последний удаляем. Ну а чего же оно тормозит-то ТЕПЕРЬ?
А сборщик мусора? В момент завершения очередного штриха, когда мы фиксируем результат операции, освобождаются некоторые ресурсы, сборщик мусора вызывается когда захочет, но почему-то всегда совсем не в тот момент, когда следовало бы. Т.е. нам бы этот процесс слегка отложить - пусть сначала все отрисуется, а потом будет время на уборку.
Шаг четвертый. Делаем статический класс Trash, который будет у нас содержать коллекцию объектов, которые надо бы удалить, но не хочется вызвать этим появление на сцене сборщика мусора. И конечно у него будет метод освобождающий весь этот хлам - в тот момент, когда мы надеемся на лучшее ничем важным не заняты. Это не гарантирует, что сборщик вызовется именно в этот момент, но скорей всего так и произойдет, особенно если подсказать системе вызовом System.gc()
Шаг пятый, шерстим весь код и избавляемся от лишнего создания/удаления объектов. Т.е. если объект можно использовать повторно, то лучше его повторно использовать. В частности не зачем для каждой операции создавать новый Bitmap+Canvas, лучше просто почистить тот, что остался от предыдущей.
И конечно лучше об этом думать сразу.