Parse & Android: рекомендации начинающим разработчикам

Аннотация
В данной статье я бы хотел поделиться общими впечатлениями от использования BaaS — решения под названием Parse для разработки бэкэнда Android-приложения, рассказать о всех «подводных камнях», с которыми мне пришлось столкнуться в период разработки.

Впервые эту платформу мне посоветовали коллеги по работе, когда я был юниором, и за плечами был всего 1 коммерческий проект. Мотивацией к написанию данной статьи послужило большое количество потраченного времени для поиска совместимых версий библиотек и обдумывание странных решений разработчиков платформы. На всякий случай в конце я оставлю все необходимые ссылки о том, что такое Parse.
Проблема №1: Использование Parse Server в связке с PostgreSQl
Использование данной конфигурации было обусловлено тем, что сервер был развернут на VDS-хостинге, и использование удаленной базы MLab было нецелесообразно, ибо на момент разработки Роскомнадзор пытался блокировать Telegram в России, и были проблемы с соединением без VPN. Настраивать VPN на консольной Linux времени не было, а проект горел, поэтому решил использовать локальную базу на сервере. Я выбрал PostgreSQL, потому что с ней у меня был хороший опыт работы.
Лайфхак № 1: чтобы база работала без ошибок в типах данных, при установке postgres нужно установить postgis. После чего необходимо создать базу и сразу же после создания создать подключить все расширения postgis. О том, как подключить расширения postgis к базе, можно почитать тут. После того, как все расширения подключены, можно подключать базу к серверу, открыть dashboard и посмотреть, что таблицы созданы без ошибок.
Лайфхак № 2: используйте версию Parse server >= 2.7.2. Когда я скачал тестовый проект с Git, там был сервер версии 2.2.5, и вроде всё работало, но впоследствие вылез один баг: при сохранении координат геолокации lat и lng менялись местами.

И здесь было 2 случая: если координаты были <90 по модулю, то маркер на карте был просто в другом месте, иначе приложение ловило краш, и в консоль падал лог о том, что Lat не должен быть больше 90 по модулю.

В течение двух суток я искал решения. Чего я только не находил на разнообразных форумах и в github issues: переворот координат в Cloud-функции (не работает!); переворот координат в PostgresStorageAdapter (после изменений возникло много ошибок). На следующий день заглянул в релизы и увидел, что в версии 2.7.2 был пофикшен баг в PostgresStorageAdapter. Быстро исправил версию в package. json, и «о, чудо!», всё заработало как надо.

На этот момент уже была версия 3.х.х, и я попытался её использовать, но разработчики внесли много изменений, связанных с Cloud-функциями, и при запуске выпадало еще много ошибок. Времени исправлять рабочий код не было, поэтому версия 2.7.2 мне подошла как нельзя кстати. Если же вы только начали свой проект, то, конечно же, лучше использовать свежую версию.
Проблема №2: Не отписываются LiveQuery
На решение данной проблемы я потратил чуть больше одного дня. И она была чертовски странной и неочевидной.

Изначально архитектура была примерно такой:
И при выходе с экрана метод вызывался, но запрос не отписывался. Как известно, LiveQuery подписывается по запросу, и любое изменение данных, соответствующих запросу, можно отследить в колбэке. Отписка так же происходит по запросу.

В методе подписки возвращается объект Subscriber, но этот объект абсолютно бесполезен, потому что метода «отписаться» он не содержит, и сам LiveQueryClient не содержит метода «отписаться» с параметром Subscriber. Включив дебаг, начал пошагово заходить в тот самый метод «отписаться». В самом клиенте приватно хранится лист подписок. В методе разработчики проходятся по этому листу циклом и сравнивают запрос из параметра с непереопределенной функцией equals, которая соответствует обычному ==, и которая сравнивает адреса у сложных объектов. Запрос хранится в объекте подписки.

И это всё объясняло. В моем проекте был класс с функциями, который создавал мне нужный запрос. И так как объект запроса всегда создавался заново, следовательно, адреса у запросов были разные, equals не срабатывал, и отписка не происходила. Решил я эту проблему следующим образом: сделал singleton, и всё заработало.

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

Надеюсь, данная статья принесет пользу. Если вы нашли какие-нибудь неточности или ошибки, напишите мне. Как и обещал, оставляю ссылки на несколько хороших источников, которые помогли мне:

  1. Что такое BaaS
  2. Что такое Parse? | 5 альтернатив Parse
  3. Документация по Parse
  4. Установка и настройка PostgreSQL на Ubuntu
  5. Как подключить PostgreSQL к Parse-серверу
Всем удачи!
Спасибо за внимание!