Как стать автором
Обновить
31
0
Отправить сообщение

Хорошо, конечно, что вы все что-то свое написали, но мне бы просто открыть диалог реактивно)

А какая именно механика переносится из view с таким подходом?

Мне нравится подход реактивного UI начиная от пользовательского действия и заканчивая базой и сетью. На тот момент не было ничего похожего на CoroutinesBinding и они были в бете. Поддержка Flow в Room вроде появилась только под Новый год. Использовать сырой подход без понимания того, кто его будет поддерживать пока не хотелось. Но в общем мы вполне рассматриваем использование Flow как замена Rx на архитектурном уровне, хотя и Rx нас всем устраивает

Да, понимание есть. На самом деле, на мой взгляд, это одна из проблем терминальных состояний в Rx и отличает корутины.
Сетевые запросы мы делаем через ретрофит и оборачиваем все в ответы в подобный объект


data class SafeResponse<T> (val data: T?, val exception: Throwable? = null)

Оборачиваем на уровне интерфейса ретрофита через подобие RxJava2CallAdapter.
Ошибка тоже пробрасывается в onNext и не приводит к завершению цепочки.
Из интеракторов тоже частично возвращаем данные в подобном формате.
И обрабатываем их следующим образом


fun <T> Observable<SafeResponse<T>>.safeResponseSubscribe(onData: (data: T) -> Unit = {},
                                                          onError: (data: Throwable) -> Unit = {}): Disposable =
        this.subscribe({
                           if (it.data != null) {
                               onData(it.requireData)
                           } else {
                               onError(it.requireException)
                           }
                       }, { onError(it) })

Для Observable<SafeResponse> у нас написаны экстеншены для упрощения работы в таком формате.
За счет этого объекта и пробрасывания ошибок в onNext мы как раз избегаем такого.

а что мешает в вашем примере использовать стандартный метод вместо кастомного?

На данном подходе у нас приложение написанное с нуля где-то полтора года назад. Тогда еще Flow если и были, то не в стабильном релизе. Если бы сейчас писали с нуля, то возможно подумали бы и о Flow. Но опять же, не видел достойных примеров, в которых можно на архитектурном уровне их использовать. Кажется, что они решают больше локальные чёткие задачи и в принципе не конфликтуют в рамках одного приложения с Rx.

Задач с такой частой периодичностью у нас нет, поэтому с такой проблемой пока не столкнулись. Вообще, странно, что через AlarmManager он работает как надо, а через WorkManager нет. Возможно, были какие-то баги (alpha все-таки) и в beta поправили? Багов связанных с периодическими задачами у них в issuetracker было достаточно)

Хороший вопрос. В каких-то случаях у нас есть своя LiveData, которая висит на Appplication, через которую пробрасываются статусы прямо из Worker; в каких-то случаях это менеджеры самописные; бывает мы слушаем результат выполнения Worker через WorkManager.getInstance().getWorkInfoByIdLiveData()

Вроде все доклады есть вот здесь, но там нужно авторизоваться, чтобы смотреть их

С ViewModel хорошее решение, добавлю его в статью. Спасибо

Да, если говорить про страницы разного типа (как минимум табы или подобные ui-элементы), то, конечно, ViewPager более удобен. Я же говорил именно про списки в любых их проявлениях

Да, вы правы про фрагмент. Ситуация именно про поведение с добавлением в бекстэк


А насчет ViewPager по следующим причинам:
1) RecycleView гибче — можно экспериментировать со свободным или постраничным скроллом, с вертикальной лентой или горизонтальной, с элементами, которые наезжают друг на друга контролами; экспериментировать с анимациями и расположением элементов.
2) Иерархия вью в этих элементах очень сложная и хочется все это переиспользовать, настраивать пул для разных типов элементов, также можно прогревать RecycledPool еще до начала использования самой ленты
3) Из-за наших особенностей хранения данных и структуры этих данных мы хотим очищать списки при уходе в глубину — с ViewPager с такой логикой возникает куча проблем, так как у него фрагменты жестко привязаны к элементам списка и логика восстановления фрагментов очень неочевидная и размазанная между нашей бизнес-логикой хранения данных, методами жизненного цикла и состояниями FragmentManager. Например у ViewPager после onDestroyView могут приходить запросы на создание фрагментов.
4) Ну и просто лишний слой в виде фрагментов и их жизненного цикла нам показался лишним и без каких-либо преимуществ использования перед RecycleView

И про Сирию в статье тоже не слова. И, если бы не комментатор сверху (зачем вообще гуглить картинки из статей?), то никто бы и не стал так ассоциировать. Если это кому-то показалось лишним, то можно было в лс написать, а не разводить тут дискуссию про политкорректность выставляя это на показ.
Напоминает серию из South Park "Сhef goes nanners"

Activity слишком много умеет, чтобы быть просто View. Поэтому, в нашем случае, там с течением времени скапливалось слишком много логики. В правильном MVC да, так и есть, вы правы.


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

1) При работе с отвязанными объектами теряется их свойство "живых обьектов", теряется возможность выборок удобных из Realm'а и нам показалось, что это дополнительные движения. Но вообще да, мы тоже думали о том, чтобы за пределами репозитория взаимодействовать с отвязанными объектами.


2) Да там ведь и не БД уже, там прогретый кеш. А пулл потоков это не городить, это группировка по типу операции, вы ведь все равно там на каком-то Sheduler'е их запускаете.

1) Как происходит изменение обьекта у вас? Например, есть таблица Parent и вам нужно добавить на него связь с новым Kid (внутри Parent список из Kid). И, если не трудно, расскажите, как вы делаете поиск по спискам. Например нужно достать Kid из Parent по имени.


2) Закрывать Realm после каждой транзакции довольно расточительно. В вашем случае стоит сделать пулл потоков для работы с Realm'ом и закрывать инстанс после работы потока, а не после транзакции. Да и если делать все операции в фоновом потоке, то это либо callback hell, либо, как вы и сделали, использовать rx. Мы же специально перешли на Realm, чтобы перенести все операции на UI поток.


3) Да, речь была про цепочку наследования. Но это мелочь.


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

вместо Kotlin'а мы выбрали Scala)

Возможно, он кидал предупреждения, если поток, на котором он был открыт, перестал работать. Смысла закрывать инстанс на UI потоке мы не увидели. После первого запроса за данными инстанс прогревается и следующие выборки уже в разы быстрее, поэтому мы вообще ушли от асинхронных выборок и все делаем синхронно блокирующим вызовом. А время запроса в другом потоке для нас чуть менее приоритетно, так как это не повлияет на пользователя и графический интерфейс. У нас нет блокирующих пользовательских операций, при любом изменении данных мы сразу же изменяем данные локально и асинхронно создаем джобу в очередь на изменение данных на сервере. Время выполнения этой работы никак не будет влиять на пользователя и заставлять его ждать.


В своих примерах они закрывают его на Activity.onDestroy(), предполагая, что в рамках этого активити показываются специфичные данные, в меньшей степени используемые в других компонентах. У нас же два активити и пара сервисов, все используют одни и те же наборы данных.


Насчет разделения на конфигурации. Это оправданно только если обьекты в этих конфигурациях будут независимыми, нам показалось это усложнением и мы отделили в отдельные конфигурации только логирование, статистику и прочую информацию не относящуюся непосредственно к пользователю.

fgtmenow Точно сейчас не скажу на сколько увеличился размер апк от Realm'а, но если разбивать на разные архитектуры и тд и тп, то можно уложиться в 1 MB. И, на самом деле, насчет сгенерированного кода и DexCount — либо это заинлайнится, либо вырежется, либо мы бы это написали руками.
Картинка к статье намекает, что никаких бенчмарков к решению не прилагается:)

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Зарегистрирован
Активность