Comments 16
Качественная работа!
Отдельное спасибо за код.
Интересный подход сам по себе.
Главный вопрос — на сколько сильно раздувается AppState в большом приложении?
Я приводил пример подхода чуть ниже в ответ на другой комментарий. Вкратце — зависит от того, как Вы построите состояние. Моё мнение в чем: При другом подходе данных меньше у Вас не станет, они просто будут разбросаны по всему приложению, часть во фрагменте, часть в интеракторе, часть ещё где-то и т.д.
В случае с Redux они просто лежат в одном месте, а всё остальное эти данные только использует, но не хранит.
Да, последовательность действительно имеет значение в данном случае и я бы даже сказал, что надо быть внимательным, но, это редко создаёт проблему, если правильно к этому подойти. Как правило у Вас будет мало случаев, когда несколько разных Middleware следят за одним и тем же событием и пытаются его заменить на что-то другое. Шанс выстрелить себе в ногу, конечно, всегда есть, но больших проблем я особо не заметил, да и логика эта хорошо покрывается тестами, что даёт большую уверенность в отсутствии регрессий. Отличный вопрос, кстати.
Возникает вопрос. А не происходит мощного усложнения читабельности единого стейта в крупных приложениях?
В принципе можно выносить в подстейты целые флоу, которые в свою очередь тоже дробить на стейты отдельных экранов, но как-то больно много вложенности, читать же неудобно… Какое решение Вы используете для таких случаев?
Ну и второй вопрос — пробовали дробить на отдельные стейты? Проблемы переживания поворота и прочего вполне легко решаются, если сделать store на базе обычной ViewModel от гугла, а каждая фича становится полностью независимой, в любой момент по feature модулям можно приложение бить.
Если пробовали, какие минусы и плюсы по ощущениям от сравнения Вашего варианта и отдельных стейтов?
В более сложной конструкции части ApplicationState описываются иначе.
Например как-нибудь вот так:
data class ApplicationState {
... some other data here
val bottomSheetState: BottomSheetState,
val currentScreenState: CurrentScreenState
}
При этом BottomSheetState и CurrentScreenState могут являться sealed классами с явно ограниченным количеством возможных вариантов
BottomSheetState.kt
sealed class BottomSheetState {
data class SimpleMessageBottomSheetState(...) : BottomSheetState()
data class MessageWithButtonBottomSheetState(...) : BottomSheetState()
}
CurrentScreenState.kt
sealed class CurrentScreenState {
data class Home(...) : CurrentScreenState()
data class Profile(...) : CurrentScreenState()
data class Settings(...) : CurrentScreenState()
}
Т.е. получается что у нас есть стейт какого-то BottomSheet'a или конкретного экрана и в момент времени активным может быть только один из. Но в тоже время в ApplicationState рядом могут лежать и другие данные, которые каждый может дергать на любом экране. Мне кажется, что в целом это баланс, между работоспособностью и достаточно простым на восприятие состоянием. Создатели Redux на JS в одной из частей документации даже описывают подход, как лучше структурировать состояние. Вкратце — более плоское состояние — лучше, сильно много вложенностей усложняют работу с такой конструкцтей.
Если под дроблением вы имели ввиду что-то другое и я не до конца ответил на Ваш вопрос — дайте пожалуйста знать, подискутируем.
А как это все дружится с разбиением приложения на модули?
Еще позволю сделать наблюдение что не все action должны быть видны снаружи store, например при некоем абстрактном search должен быть action = SearchChanged который посылает view в store, он обрабатывается middleware, который загружает данные и собирает некий внутренний action = DataUpdated, который в свою очередь обрабатывается reducer и изменяет state. Так вот по моему мнению action=DataUpdated не должен торчать наружу, т.к. нарушается инкапсуляция и у разработчика появляется дополнительная возможность чего-нибудь сделать не так.
Для показа Snackbar'a в примере со вторым приложением я тоже использовал middleware. Он следил за единственным интересующим его событием и показывал сообщения, когда что-то прилетало. Я примерно понимаю что Вас смущает в случае с событием DataUpdated, то, что оно пролетит через все Middleware и другие Reducer'ы, потенциально давая возможность прострелить колено, но, в этом весь Redux, это фундаментальный его механизм, сложно будет сделать иначе не нарушив изначальную идею.
Android + Redux = <3