Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor DataState.Loading #6

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

brady-aiello
Copy link

Summary

Loading state should display both the loading indicator, and whatever UI is already showing. This means remembering the last non-Loading state. Got around this issue by using remember { } in Composables, but this issue will come up again in Swift UI, as all UI are emitted as distinct, whereas the Loading UI is a combination of the Loading indicator and the current UI state. We got away with this fine with the Android View system and UI Kit, as they implicitly held state. But we can no longer, and should no longer, rely on Views to hold state.

Fix

Make DataState.Loading hold on to the last non-Loading state emitted, so they can both be displayed at the same time. This could also be solved via a SharedFlow with a cache of 2. However, I didn't want to worry about translating that cache to Combine or RxSwift if we adopt that later on. Adding a single parameter to Loading seemed like the simplest solution.

  • dependency update: updated AGP to 7.1.0-alpha03 to keep current with Android Studio Bumblebee 2021.1.1 Canary 3

Testing

  • ./gradlew :app:build
  • ./gradlew :shared:build
  • xcodebuild -workspace ios/KaMPKitiOS.xcworkspace -scheme KaMPKitiOS -sdk iphoneos -configuration Debug build -destination name="iPhone 8"
  • manual testing of clicking and swipe-to-refresh on iOS and Android

[Summary]
Loading state should display both the loading indicator, and whatever UI
is already showing. This means remembering the last non-Loading state.
Got around this issue by using remember { } in Composables, but this
issue will come up again in Swift UI, as all UI are emitted as distinct,
whereas the Loading UI is a combination of the Loading indicator and the
current UI state. We got away with this fine with the Android View
system and UI Kit, as they implicitly held state. But we can no longer,
and should no longer, rely on Views to hold state.

[Fix]
Make DataState.Loading hold on to the last non-Loading state emitted, so
they can both be displayed at the same time. This could also be solved
via a SharedFlow with a cache of 2. However, I didn't want to worry
about translating that cache to Combine or RxSwift if we adopt that
later on. Adding a single parameter to Loading seemed like the simplest
solution.

- dependency update: updated AGP to 7.1.0-alpha03 to keep current with
  Android Studio Bumblebee 2021.1.1 Canary 3

[Testing]
- `./gradlew :app:build`
- `./gradlew :shared:build`
- `xcodebuild -workspace ios/KaMPKitiOS.xcworkspace -scheme KaMPKitiOS
    -sdk iphoneos -configuration Debug build -destination name="iPhone 8"`
- manual testing of clicking and swipe-to-refresh on iOS and Android
- Updating Ktor
- Adding timeouts to network requests
brady-aiello referenced this pull request Jul 14, 2021
[Description]
Jetpack Compose is going stable in July 2021, and we want to show folks
the easiest way to get started with KMM using Compose.

[Solution]
- Add Compose UI, and support SwipeRefresh using Accompanist.
- Remove XML layouts.

[Testing]
- ./gradlew :shared:build :app:build
- manual testing
@@ -24,7 +24,7 @@ class BreedViewModel : ViewModel(), KoinComponent {
private val scope = viewModelScope
private val breedModel: BreedModel = BreedModel()
private val _breedStateFlow: MutableStateFlow<DataState<ItemDataSummary>> = MutableStateFlow(
DataState.Loading
DataState.Loading<ItemDataSummary>()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: you should be able to remove the type param right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I was getting a crash without it; I think was a Koin issue. I just added it back in, and not getting the crash, so I'll remove it again.

brady-aiello added a commit that referenced this pull request Jul 19, 2021
[Summary]
The Loading UI is usually shown in conjunction with other UI, such as an
error view, or valid data. Consuming it with a when statement and
treating it like any other state may not make sense with Compose and
Swift UI. I tried a different approach here, giving the Loading state
the last valid DataState as well:
#6

[Fix]
In this PR, I'm using the classic NetworkBoundResource approach, where
the DataState is not a sealed class; instead, it contains nullable
versions of all possible states.

[Testing]
- `./gradlew :app:build`
- `./gradlew :shared:build`
- `xcodebuild -workspace ios/KaMPKitiOS.xcworkspace -scheme KaMPKitiOS
    -sdk iphoneos -configuration Debug build -destination name="iPhone 8"`
- manual testing
russhwolf added a commit to touchlab/KaMPKit that referenced this pull request Aug 5, 2021
* Update badges to touchlab-lab

* [Issue-0000] Upgrade to Gradle 7

[Description]
Preparing for introducing Compose, which requires Android Studio Canary,
which requires Gradle 7+

[Solution]
- Upgrade Gradle and Android Gradle Plugin
- Make necessary changes to accomodate the new Gradle and AGP APIs

[Testing]
- ./gradlew build
- manual testing of Android and iOS apps

* Update workflows to setup Java 11, update PR template

* [Issue-0000] Add Jetpack Compose

[Description]
Jetpack Compose is going stable in July 2021, and we want to show folks
the easiest way to get started with KMM using Compose.

[Solution]
- Add Compose UI, and support SwipeRefresh using Accompanist.
- Remove XML layouts.

[Testing]
- ./gradlew :shared:build :app:build
- manual testing

* Update Compose dependencies to use 1.0.0-rc01

* Use derivedStateOf for isRefreshingState

* [Issue-0000] Alternative Loading state refactor

[Summary]
The Loading UI is usually shown in conjunction with other UI, such as an
error view, or valid data. Consuming it with a when statement and
treating it like any other state may not make sense with Compose and
Swift UI. I tried a different approach here, giving the Loading state
the last valid DataState as well:
touchlab-lab#6

[Fix]
In this PR, I'm using the classic NetworkBoundResource approach, where
the DataState is not a sealed class; instead, it contains nullable
versions of all possible states.

[Testing]
- `./gradlew :app:build`
- `./gradlew :shared:build`
- `xcodebuild -workspace ios/KaMPKitiOS.xcworkspace -scheme KaMPKitiOS
    -sdk iphoneos -configuration Debug build -destination name="iPhone 8"`
- manual testing

* Lint fix

* Simple SwiftUI implementation

* Compose reorg and lifecycle-aware flow

* Compose preview

* SwiftUI preview

* Misc config adjustments and cleanup

* Make entire row clickable in SwiftUI

* Bump to release versions

* Revert badges

* Run ktlintFormat

* Bump to Compose 1.0.1 and Kotlin 1.5.21

* Remove extra derived state

* Oops

Co-authored-by: Brady Aiello <brady.aiello@gmail.com>
Co-authored-by: Brady Aiello <brady@touchlab.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants