Написать программу для бега для Андроид. Сервис записи трека.

Запись трека

Саму запись трека вынес в отдельный сервис, так как activity перезапускается, выгружается и т.д. К тому же, если приложение падает в дамп, то сервис автоматически восстанавливается самой OS. То есть чтобы извне прекратить запись трека можно только выключить телефон или отключить GPS.

Каждое получение координат обновляет трек в базе – это сделано, чтобы ни в коем случае не потерять данные при любых сбоях программы или устройства. Что мне не нравилось в том же runkeeper – пока не нажмешь кнопку “сохранить” – трек висит в памяти. При этом любой глюк и весь твой трек потом полученный 20 километровый трек – пропал без следа. И у меня так уже было… Здесь же, трек сохранится вплоть до выключения телефона. Даже если бежишь марафон и телефон умирает перед финишем – весь твой трек сохранится.

На этом этапе считаю, что запись трека достаточно надежна.

Kotlin + Mockito.any()

Опять наткнулся на несовместимость Kotlina и Mockito.

В kotlin нельзя использовать оператор any(). При компиляции ругается на NotNull у метода. Можно конечно сделать параметр тестируемой функции Nullable, но подгонять код ради теста – это не правильный путь :)

Сначала решил это с помощью конструкции:

  testMethod( any(MyClass::class.java) ?: MyClass() )

Да,  это сработало, но что, если у MyClass нет конструктора по умолчанию? Или в конструкторе выполняются какие то действия влияющие на все экземпляры класса или окружение?

После поисков в интернет натолкнулся на отличный способ, который я добавил в свой класс TestHelper:

fun <T> Any.anyK(): T {
    Mockito.any<T>()
    return uninitialized()
}
fun <T> uninitialized(): T = null as T

Теперь можно написать просто:

testMethod( anyK() )

 

Dagger 2 + Service

Пытался прикрутить сервис к интерактору через dagger, но как это сделать? При создании интерактора сервис еще может быть не создан. Использовать сервис через app.getMyService() тоже не хочется, так как это зависимость от app, могут возникнуть проблемы с Unit-тестами, которые не знают о пакете android.

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

После долгих попыток как то прикрутить сервис решил поменять сам подход. Не сервис внедрять в интератор, а интерактор внедрять в сервис. Так, сервис, когда запускается, то сам сообщает о том, что он запустился и передает ссылку на себя интерактору. После этого интерактор может спокойно использовать сервис по назначению. Плюс этого подхода еще в том, что, если сервис недоступен, то интерактор может сам рулить логикой приложения. Например выдавать ошибку или складывать команды в очередь, чтобы передать их сервису когда он станет доступным. А не тестируемый сервис становится простым исполнителем, так как вся бизнес логика находится там где они и должны быть – в интеракторе.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Facebook Auto Publish Powered By : XYZScripts.com