I am Fluttered

@iamfluttered.bsky.social

My journey of learning Flutter daily.

Day 31: I have been tinkering with syncing my offline sqlite DB with my remote database and damn it’s hard. Recently, I found out about powersync and their cool plug and play solution for exactly this. They have nice dart package for it and it also works with drift DB. Very promising. #flutter

Day 30: Just realised that you in fact can set dynamic default values (eg created_at timestamp) for your freezed models. You can’t use the @Default annotation, but you can use the ._() private constructor and set it up in there. Very cool. #flutter

Day 28: Today I found out that using .setPrefferedOrientations() is not optimal as it is applied only when the flutter engine fully loads. To prevent weird rotations on the splash screen, always define allowed orientations directly on the native layer (info.plist or MainActivity.kt) #flutter

Day 27: Today I tried seeding Darts random number generator with user uuid. It basically allows you to store extra info about the user without a DB. I used it to get a random anon avatar from the list of anon avatars based on that user uuid in a deterministic way. What a cool usecase #flutter

Day 26: Today I played with driftDB table streams. I listen to them in bloc to refresh UI, but listening to changes of just single table is not enough with foreign keys. That’s why I used rxDart CombineLatestStream to listen to multiple tables at once, covering changes in connected tables #flutter

Day 25: Today I discovered the power of having a single public “GlobalKey<NavigatorState>” and setting it as navigatorKey in my root GoRouter. With it, I can get a global context from anywhere in the app, which allows me to open dialogs and change routes without the current BuildContext. #flutter

Day 22: Today I was working with super_drag_and_drop package to add image drop support for our flutter web app. It’s much faster then searching for images in explorer and it’s also cross platform so I can reuse this code in our mobile app later. Very cool. #flutter

Day 20: Today I was working with JWTs for authentication in my app. I was happy to find out how easy it is to store these tokens securely using flutter_secure_storage. The support for the web is currently only experimental but for other platforms it’s really great! #flutter

Day 19: Today I worked with drifts db reactive streams for the first time and so far it’s amazing. I really love to use Flutter streams whenever I can so I tried combining bloc with the drift streams and it makes a really powerful combo when it comes to reactive UI.

Day 18: Today I used injectable’s micro packages to auto inject dependencies across multiple flutter packages. I was afraid it won’t be possible with injectable and that I will have to use getIt manually, but fortunately it works as a charm.

Day 17: Today I created my first internal package for my app to isolate shared core logic from the UI. Since it has its own pubspec.yaml, it makes dependency management much cleaner and helps to enforce proper separation of concerns.

Day 16: Today I was adding translations from scratch to one of my projects. I used intl package and I must say it was surprisingly really very easy and quick to implement. Plus adding AppLocalization extension to BuildContext makes it easy to acess translations without any hassle.

Day 15: Today I tried to use go_router package instead of traditional Navigator and I really love it. It’s declarative nature makes the navigation in the app feel more “stable” and predictable. Plus it works great on the web. I don’t think I can go back to Navigator now…

Day 14: Today I found out about flutter_dotenv package which allows you to load environment variables from .env file. I always assumed that env file is used only in JavaScript world, but it’s nice to see that Flutter uses it too.

Day 13: Today I finally convinced myself to uninstall classical Flutter SDK, and fully switch to fvm (flutter version manager similar to nvm). Switching Flutter versions for different project is much easier this way. It’s like nvm for node.js which I already know so the transition was very easy.

Day 12: Flutter official docs recommend to use so called “command patter”. Just realised that when you are using bloc, you are also automatically in compliance with the command patter, because emitting bloc events is the exactly same as executing command, just with different naming.

Day 11: Today I discovered the “injectable” package and I already love it. I really missed the annotation based dependency injection in Flutter, as I was used to it from Android’s Dagger Hilt and from Spring magic beans. The get_it package is great but with injectable, it’s a whole different beast.

Day 10: Today I got a chance to use the Navigator widget for the first time. I was suprised how easy it is to create a nested navigation sub views inside the main view, with just few lines of code. Very cool.

Day 9: Today I found out about extensions on BuildContext, which creates a nice syntax sugar that allows you to directly access what you need, directly from the context, without a need to write xxx.of(context)

Day 8: Today I found out about extending your widget with InheritedWidget and adding a static “of” method to it, which uses “context.dependOnInheritedWidgetOfExactType” to easily access some data from anywhere in the app. Very cool combo.

Day 7: Today I found out that a popular http client library Retrofit, which is super popular among Android developers, is also available for Flutter. Also, if you have ever worked with it using Kotlin, you will be right at home with the dart version as it’s very similar.

Day 5: Today I found out that GIPHY package work seamlessly also on the Flutter web. There was no need to change anything in the existing codebase for mobile platforms, it was just copy-paste and done. What a great cross-platform support.

Day 4: Today I found out that when you call print in your dart code, it’s output is shown not only in the IDE console, but also in the browser console, that is if you run your app with the target set to web.

Day 3: Today I found out that performance wise it is better to decompose large widget trees into smaller stateless/statefull widgets, rather than into methods in the parent widget. Separate widgets have its own context and can be marked as const to optimize rebuilds.

Day 2: Today I found out about compute() function, which runs the given computation on a new isolate. In my case, I used it for background image compression that would otherwise caused a significant UI lag.