What I learnt at Flutter ByteConf — Day 1

The first flutter byteconf started today with three workshops. Here’s what I learnt

Daniel Llewellyn
6 min readAug 14, 2020

I was excited about ByteConf flutter for a while, and the first three workshops had some great bits in it. I’ve been working on professional flutter projects for just over a year now, but the pace of change in Flutter land and the project deadlines means a lot of things other people are doing pass me by. Sitting down to watch these presentations, here are some of the things I learnt that I didn’t know before — some relevant to the core presentation, others that I just didn’t know. Here’s the full day if you’re interested enough to have a look

https://www.youtube.com/watch?v=ulbY6QcVzzI

BLoC ❤ Cubit

The first presentation was about BLoC and Cubit, BLoC being my preferred library — and Cubits something I have not come across before.

New things

The whole point of the presentation was to present Cubits and that they now interop well with BLoC. Cubits are essentially lightweight versions of BLoC — here’s an example

class CounterCubit extends Cubit<int> { 
CounterCubit() : super(0);
void increment() => emit(state + 1);
}

The equivalent BLoC looks more like this:

A neat summary is in the youtube video, but effectively — Cubit is BLoC without the Events, instead it just exposes functions to the user. This is simpler, but less tracable.

Read full info here:

Some things that passed me by

  • Bloc test

I had not realised that BLoC test allowed you to use explicit type parameters. I had written my tests like this:

blocTest(
'CounterBloc emits [2] when CounterEvent.increment is added twice',
build: () => CounterBloc(),
act: (bloc) => bloc..add(CounterEvent.increment)..add(CounterEvent.increment),
skip: 1,
expect: [2],
);

But you can actually specify the types:

blocTest<CounterBloc, CounterEvent, CounterState)(
'CounterBloc emits [2] when CounterEvent.increment is added twice',
build: () => CounterBloc(),
act: (bloc) => bloc..add(CounterEvent.increment)..add(CounterEvent.increment),
skip: 1,
expect: [2],
);
  • Observers

A simple idea that had never occurred to me was to log all events and states using a Bloc observer — extremely useful for tracking states an errors.

  • On Error

In both cubits and blocs you can override this to capture all errors.

@override void onError(Object error, StackTrace stackTrace) { 
print('$error, $stackTrace');
super.onError(error, stackTrace);
}

Bit embarrassed I didn’t know this, but there we go..

Single state

I’ve been using the BLoC library for a little while, but it was interesting to see the way that the state was handled — it is more reminiscent of MVI than of how I usually use BLoC. It’s less verbose and a lot easier for the UI to consume if you have all the data in once state object, as opposed to what I’m used to doing now — which is have a different State for error, loading etc and a big switch statement in BlocBuilder.

Here’s the State object that was used in the video:

Rx Operations

I’m less embarrassed about missing this bit, but the idea of you using RxOperations inside your BLoC is very powerful, as illustrated in this code snippet:

The code above will basically make sure that the events aren’t fired more than every 350ms, in the example the video runs through it’s a search term and using this line in the BLoC means that it doesn’t trigger every keystroke, but every 350ms.

Package structure

The package structure used in the project for the demo (https://github.com/felangel/fluttersaurus/) is very nice — where the bloc, repository, views and widgets are all stored together. I very much like this as a pattern.

Grey loading state

I’ve seen a few widgets that can do this sort of thing before, but the loading state for search is done with

Shimmer.fromColors

which gives a nice grey loading state on search results, looks very nice — and very simple.

Learn to soar with Flutter

Our next talk had a promising start, with the screenshare of DartPad — fun to see a talk without any full IDE. This presentation was targeted more at new Flutter developers, and if I had to recommend one of the three videos to someone who’s new to flutter then this is the one I’d suggest looking at.

There’s a lot of useful things in there and here are some of my favourites;

TextThemes

In projects I do at home, I always use TextThemes and set it up in the main class to propagate the different styles. Then, you can get the theme like this:

style: Theme.of(context).textTheme.headline2

The only catch is you have to use the text styling names that flutter wants you to.

Navigation

There’s a number of ways to handle navigation in flutter, the worst one is the one I usually end up doing in my projects — just inline push material widgets. One of the nicer ones when using Bloc is to have a Bloc to deal with navigation — the option discussed in this video is to use routes inside MaterialApp and use PushNamed and Pushnamed with arguments to navigate around; which feels like a good place to meet in the middle. Easy to get going. Easy to maintain.

Forms

Forms are a recurring feature of application development — and they’re also easy to understand. The talk goes through callbacks from forms as a nice way to update the progress bar. Also it handles enabling and disabling buttons. In short a lot of nice things that we have to do with forms very often.

Animations

This video is a very gentle introduction to animation and builds a really neat animation for the progress bar. It covers vsync, animation controllers, changing colours using Tweens, AnimatedBuilder and then gluing it all together with state.

Worth a watch, especially for new flutter devs!

Kotlin multiplatform / Flutter

This was the talk I was most excited about. When someone asks me — full disclosure, most of my career has been an Android developer — do you prefer native or flutter? I’m torn. On the one hand, Kotlin is easily my favourite language, on the other, even aside from the cross platformness of Flutter, I do really enjoy writing Flutter UIs. So this presentation was incredibly interesting.

As you’d expect, this presentation had a lot of gaps, as it’s trying to succinctly cover a huge area but it was an impressive demonstration of solving a lot of the problems I’ve had with my previous endeavours with multiplatform kotlin.

Project structure

The project structure was the first interesting thing I noticed — the flutter app in Android studio was set up, as you’d expect, but with an SDK folder inside the root. This project then contained the ‘SDK’ which is to say the Kotlin multiplatform part of the app.

The SDK project then had commonSrc, iosMain and androidMain.

The common project contained:

  • Entity classes e.g. serializable models
  • Interactors e.g. the core logic
  • Utils e.g. networking logic

Our video continued with some gradle project setup — and focused mostly on the Android project and getting that one to run, although mentioned that the iOS setup is actually more straightforward.

Platform channels & Pidgeon

Moving on, the project setup was based around setting up some method channels to call through the code — before abruptly stopping to show us a better way of doing it using pidgeon

Full information here

This is a plugin that makes platform channels — i.e. calling swift and kotlin from Flutter — significantly easier than doing it by hand. As the talk carried on, the conversation and platforms where all done ‘by hand’ that is to say, manually converting the string ‘method calls’ to a kotlin function.

It was a good presentation because of how raw it was — and it really emphasises how many challenges there are. First setting up the calls themselves, then mapping errors between the two interfaces, then serializing in kotlin and deserializing in Flutter. It is also error prone — lots of string matching is a recipe for unusual errors.

That said, the benefits of using kotlin multiplatform are huge due to a nice language and a great ecosystem, and the challenges of interacting with the multiplatform code from dart is comparable with the challenges of interacting with a backend server (i.e. deserializing and serializing) and this presentation was done without the benefit of pidgeon.

Conclusion

I’ve already started taking an app that I’ve previously written and applying things from the first talk — namely cubits, and refactoring the package and I’ll soon be looking to integrate it with my Kotlin multiplatform SDK as per the 3rd talk — not to take away from the second which is an excellent presentation for getting to grips with flutter.

--

--