Быстрее, чем когда-либо: ускорили работу экрана «Планы» в мобильных приложениях
4 650
06 марта 2024

Быстрее, чем когда-либо: ускорили работу экрана «Планы» в мобильных приложениях

Свежий релиз, в котором мы «разогнали» работу экрана «Планы» в мобильных приложениях, прошёл незаметно — никто не сказал «вау!». А на самом деле «под капотом» пришлось проделать огромную работу. Зачем и почему — расскажем ниже. Но сначала немного о том, чем хорош режим «Планы».

deadline4

Зачем вообще нужен режим «Планы» #

Планы — системная папка в меню Сингулярити, где списком выводятся задачи на каждый день. В мобильной версии, когда вы скроллите список задач, сверху синхронно скроллируется список дат.

Просматривая дела в таком режиме, вы легко можете оценить количество задач на день и неделю, а также быстро записать задачи на будущее. Для перехода к нужной дате достаточно нажать на название месяца вверху окна — откроется попап с календарём, который можно листать на месяцы вперёд. Чтобы вернуться к текущему дню, стоит нажать справа вверху «Сегодня».

Переход к нужной дате в режиме «Планы»

Во всплывающем календаре и в списке дат вверху окна «Планы» всегда видно, есть ли задачи на конкретный день: дни, когда что-то уже запланировано, отмечены серой точкой-индикатором. Это помогает быстро ориентироваться в свободных датах.

Производительность: что пошло не так #

Сингулярити поддерживает неограниченную вложенность задач: их можно складывать друг в друга на сколько угодно уровней вниз. Отказываться от этого мы не планируем, поскольку функцией активно пользуются. Хотя, больше 5 уровней на практике мы не видели.

Однако вложенность создает некоторые проблемы. Например, у вас есть родительская задача «Написать материал про ритейл», у которой назначена сегодняшняя дата. К ней вы добавили несколько дочерних — с другими датами: например, рисерч вы хотите закончить только через неделю, а черновик написать через полторы.

Вопрос: а нужно ли показывать дочерние задачи, если вы смотрите расписание в «Планах» на сегодня?! Так сразу и не скажешь. Такие коллизии у нас исторически называются «миньоны», почему так — уже не помним, но подобного много. Пример с вложенными задачами просто самый очевидный.

Для решения этих «миньонов» наш код строит деревья задач. В случае экранов с планами — отдельное дерево на каждый день. Просто потому, что одна и та же задача в некоторых случаях может попасть сразу в несколько дней. Причем, с разной вложенностью в дочерние.

На вкладке «Планы» в задачах на конкретную дату выводятся вложенные со своими датами. Плюс те же вложенные задачи выводятся отдельно в нужный день

Это не было большой проблемой по производительности, пока при планировании повторяющихся задач в расписании и в Планах выводился только ближайший экземпляр такой задачи. Но стало проблемой, когда мы начали выводить повторяющиеся задачи на пару лет в будущее. Ведь повторяющиеся задачи тоже бывают вложенными :) А значит, сразу выросло число дней, на которые запланированы задачи и деревья для которых теперь нужно построить. Как мы «разогнали» работу приложения в мобильной версии. Очевидные оптимизаци особенного прироста в скорости не давали. В итоге мы решили проблему отдельными потоками загрузки:

  1. При старте мобильного приложения в отдельном потоке прогревается кеш деревьев. Отдельный поток нужен, чтобы задействовать отдельное ядро мобильного процессора вашего устройства и не «замораживать» основной экран.
  2. Кеш деревьев прогревается на 10 дней от текущей даты. Если нужно просмотреть более далекие даты, при скролле мы организовали динамическое построение деревьев по принципу Lazy Load (та самая ленивая подгрузка, которая отложена до момента, пока данные действительно не станут необходимы). Оно работает так же, в отдельном потоке — а значит, пользователь не видит торможения при пролистывании списков.
  3. Если в Планах нужно перейти на какую-либо дату в будущем через попап календаря — мы так же строим в отдельном потоке фрейм с кешем деревьев на 10 дней вперед или назад.

Самая ювелирная работа здесь проделана при пролистывании списка назад, из будущего в прошлое. Обычный Lazy Load подразумевает постепенную подгрузку данных вниз списка, но в случае отмотки дат в прошлое приходится пополнять список сверху. Это могло приводить к «прыжкам» интерфейсов. Особенно на инерционных скроллах (когда вы листаете страницу, а она еще какое-то время скроллится по инерции, хотя вы ее уже не трогаете). Но мы справились.

Вроде бы, мелочь. Но потребовалось настойчивость. И почти 2 недели кропотливого труда. Всё, чтобы было хорошо. И чтобы вашим планам в Сингулярити ничто не помешало сбыться :)

deadline2