Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upRefactor JetNews to use unidirectional data flow #116
Conversation
Several large refactors to land this:
- Removed RefreshableUiState
- Reworked UiState to allow data, error, and loading at the same time (to support all use cases)
- Removed effects architecture and restructured using ViewModel
- Refactored Repository to expose Flow and suspend functions throughout
- Deleted JetNewsStatus global state
Composables of screens were refactored to follow hoisting best practices
- Each screen has a single stateful composable paired with a stateless composable at the top level
- Stateful composabels use ViewModel to manage state
- Added slots where appropriate to avoid too many parameters
ArticleScreen:
- Moved favorites to ViewModel from JetNewsStatus
- Refactored composables to use new state
HomeScreen:
- Renames to make composables names match their function
- Added slot to LoadingContnent to extract a composable focused on initial load and swipe to refresh
- Renamed HomeScreenBodyWrapper to HomeScreenErrorAndContent to better match function
- Added empty UI state if the initial load fails ("Tap to load content")
- Hoisted snackbar state to ViewModel and made HomeScreenErrorAndContent stateless
- Renamed all composables related to displaying the post list to PostList from HomeScreenBody etc.
- Used unidirectional data flow throughout post list composables
- Renamed LoadingHomeScreen to FullScreenLoading to better match function
- Animated ErrorSnackbar on entrance and exit using AnimatedVisibility
InterestsScreen:
- Introduced TabContent object to describe a tab and it's composable content, this allows for slot usage for screen-level composables
- Stateless InterestScreen now takes a List<TabContent> which describes the tabs and their content
- Renamed InterestScreenBody to TabContent to better match function
- Moved selected topics to ViewModel, and removed global state
- Renamed *Tab composables to *List composables (e.g. TopicList) to better match function
- Removed string-key from topics, and introduced TopicSelection for TabWithSections
- Moved all previously global state into Repository (which is a singleton)
- Use unidirectional data flow throughout this screen
SwipeToRefreshLayout:
- Added TODO to document a know bug (b/164113834) that this code works around
- Disable swiping when state.value == true to avoid a bug created by duplicated state showing an infinite loading spinner
.../src/main/java/com/example/jetnews/data/interests/InterestsRepository.kt
Outdated
Show resolved
Hide resolved
.../java/com/example/jetnews/data/posts/impl/BlockingFakePostsRepository.kt
Show resolved
Hide resolved
.../java/com/example/jetnews/data/interests/impl/FakeInterestsRepository.kt
Outdated
Show resolved
Hide resolved
...src/main/java/com/example/jetnews/data/posts/impl/FakePostsRepository.kt
Outdated
Show resolved
Hide resolved
JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsStatus.kt
Outdated
Show resolved
Hide resolved
JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeViewModel.kt
Outdated
Show resolved
Hide resolved
...ws/app/src/main/java/com/example/jetnews/ui/interests/InterestsScreen.kt
Outdated
Show resolved
Hide resolved
...ws/app/src/main/java/com/example/jetnews/ui/interests/InterestsScreen.kt
Outdated
Show resolved
Hide resolved
...ws/app/src/main/java/com/example/jetnews/ui/interests/InterestsScreen.kt
Outdated
Show resolved
Hide resolved
...ws/app/src/main/java/com/example/jetnews/ui/interests/InterestsScreen.kt
Outdated
Show resolved
Hide resolved
|
LGTM with minor comments! |
.../src/main/java/com/example/jetnews/data/interests/InterestsRepository.kt
Outdated
Show resolved
Hide resolved
JetNews/app/src/main/java/com/example/jetnews/data/posts/PostsRepository.kt
Outdated
Show resolved
Hide resolved
JetNews/app/src/main/java/com/example/jetnews/ui/article/ArticleScreen.kt
Outdated
Show resolved
Hide resolved
JetNews/app/src/main/java/com/example/jetnews/ui/article/ArticleScreen.kt
Outdated
Show resolved
Hide resolved
JetNews/app/src/main/java/com/example/jetnews/ui/article/ArticleScreen.kt
Show resolved
Hide resolved
...ews/app/src/main/java/com/example/jetnews/ui/article/ArticleViewModel.kt
Outdated
Show resolved
Hide resolved
JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeViewModel.kt
Outdated
Show resolved
Hide resolved
JetNews/app/src/main/java/com/example/jetnews/ui/home/HomeViewModel.kt
Outdated
Show resolved
Hide resolved
|
Stopship! I think scoping ArticleViewModel to fragment/activity is preventing the postId from being updated after the initial load |
.../java/com/example/jetnews/data/posts/impl/BlockingFakePostsRepository.kt
Outdated
Show resolved
Hide resolved
...src/main/java/com/example/jetnews/data/posts/impl/FakePostsRepository.kt
Outdated
Show resolved
Hide resolved
JetNews/app/src/main/java/com/example/jetnews/ui/article/ArticleScreen.kt
Outdated
Show resolved
Hide resolved
…l with the previous postId.
- prefer observe* name for Flow returning functions in Repository - Make Set<T>.addOrRemove an internal extension function and use it throughout - Deprecate sample implementation of ViewModelLifecycleScope as it is intended to be replaced with a public API - Add missing comments to ArticleViewModel.kt - Corrected comments about viewModel scope to say Activity instead of Application - Added MapExtensions.kt that contains an internal extension addOrRemove - Swapped to use the liveData builder for ArticleViewModel.post
… and re-order parameters to match stateless.
…nstances on rotation.
|
Thanks for reviews! Updated based on comments. Please take a look again. |
…effect similar to the previous architecture. Re-add ViewModel when https://issuetracker.google.com/issues/165642391 is fixed Changes: - Created launchUiStateProducer effect to safely call suspending data producers from compose and return refreshable UI state - Removed ViewModel from HomeScreen, InterestsScreen and ArticleScreen - Refactored stateful screen composables to use the new loading effect
…ent, return State<T>, and use a Channel instead of a ConflatedBroadcastChannel.
|
LGTM |
.../java/com/example/jetnews/data/interests/impl/FakeInterestsRepository.kt
Outdated
Show resolved
Hide resolved
.../java/com/example/jetnews/data/interests/impl/FakeInterestsRepository.kt
Outdated
Show resolved
Hide resolved
.../java/com/example/jetnews/data/interests/impl/FakeInterestsRepository.kt
Outdated
Show resolved
Hide resolved
JetNews/app/src/main/java/com/example/jetnews/ui/article/ArticleScreen.kt
Outdated
Show resolved
Hide resolved
...ews/app/src/main/java/com/example/jetnews/utils/LaunchUiStateProducer.kt
Outdated
Show resolved
Hide resolved
...ews/app/src/main/java/com/example/jetnews/utils/LaunchUiStateProducer.kt
Show resolved
Hide resolved
...ews/app/src/main/java/com/example/jetnews/utils/LaunchUiStateProducer.kt
Outdated
Show resolved
Hide resolved
...ews/app/src/main/java/com/example/jetnews/utils/LaunchUiStateProducer.kt
Show resolved
Hide resolved
...ews/app/src/main/java/com/example/jetnews/utils/LaunchUiStateProducer.kt
Show resolved
Hide resolved
.../java/com/example/jetnews/data/interests/impl/FakeInterestsRepository.kt
Outdated
Show resolved
Hide resolved
...src/main/java/com/example/jetnews/data/posts/impl/FakePostsRepository.kt
Outdated
Show resolved
Hide resolved
...ews/app/src/main/java/com/example/jetnews/utils/LaunchUiStateProducer.kt
Show resolved
Hide resolved
...ews/app/src/main/java/com/example/jetnews/utils/LaunchUiStateProducer.kt
Outdated
Show resolved
Hide resolved
...ews/app/src/main/java/com/example/jetnews/utils/LaunchUiStateProducer.kt
Outdated
Show resolved
Hide resolved
...ews/app/src/main/java/com/example/jetnews/utils/LaunchUiStateProducer.kt
Show resolved
Hide resolved
|
Manually merged to develop w/ squashes. |

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.

Several large refactors to land this:
Composables of screens were refactored to follow hoisting best practices
ArticleScreen:
HomeScreen:
InterestsScreen:
SwipeToRefreshLayout: