I built the same feature — a list with offline cache and pull to refresh — in three frameworks. The codebases were different but the regrets were identical.
Flutter: the UI was the easy part. The mental shift was accepting that a widget rebuild is cheap only if you make it cheap. I had to learn to keep state out of the tree.
Swift: everything reads beautifully until you hit SwiftUI's navigation state, and suddenly the clean code is a stack of enums and paths. Also, iOS reviewers will find the one screen you didn't test.
Kotlin: coroutines made the async part pleasant, and then the lifecycle bit me. A scope tied to the wrong owner leaks in ways that are hard to reproduce.
The shared lesson: the list is never the feature. The cache invalidation and the empty state are the feature, and every platform makes those boring in a different way.
Which one would you pick next time?
Top comments (0)