Hi, thanks for listening. This is the It's All Widgets Flutter podcast. My name is Solo Korn. Each episode, we get a chance to speak with another amazing member of the Flutter community. This episode, we are extremely lucky to speak with Rohde. Welcome. Hey, how's it going? Good. Thanks for being on. So to start, can you share a bit about your background? Yeah, absolutely. I've been using Flutter since Flutter Beta 3, and it's been a long time, but I've been really excited about being on this journey.
I am currently at Google working on the developer solutions team, which means that we are doing cross-dev row work, being able to help a lot of teams leverage multiple products together. And that includes Flutter. So I'm trying to get people excited about using new tech and trying to figure out how to make it work for their workflows. It's amazing. As you mentioned, you started with Flutter back in the beta. How did you first hear about it? Do you remember?
Yeah, so I was a C Sharp dot net developer at the first company that I was working at. And we were doing this mortgage company software, got into building native iOS application. And it was pretty interesting. Switch was actually my first language. And so I was learning native development.
And like a lot of people face, the market was we want an Android app and I didn't have an Android app. So I looked into building one natively. And after that, it got really difficult to build both in parallel since I was a single dev shop there. And so what we did is I explored React Native. I explored Capacitor or Ionic at the time. I also explored...
And Flutter was the only solution that I could get running quickly, natively, and was just super impressed by the hot reload. I didn't have to reach out to JavaScript yet, which, you know, I'm a huge JavaScript fan, but...
it was a you know coming from C sharp dart was actually really approachable and in fact at the time Android Studio could you could take Java code and copy and paste it and it would convert it to dart which I thought was really interesting and vice versa but um
Yeah, so it was really about trying to find a solution that would help me unlock more velocity. And by having native Swift and Objective-C and Kotlin and Java experience, I was able to make a lot of plugins for Flutter really quickly. This was actually before SwiftUI and before Jetpack Compose, so this was like Kotlin and Swift in the very early days, which was interesting. And so...
Had a series of software engineering jobs after that, and then a DevRel job, and then got to Google. And then for the last three years before this last team, I was working on material design and helping out with Flutter stuff there too.
Nice. For people listening, if you want to hear more about Rody's story or his background, we recorded an episode, I think maybe three years ago now, but we'll include a link to that episode in the show notes. The reason I asked Rody to come back on to a second episode, because of this new package you're working on. It's called Signals. I've been following it pretty closely. I'm pretty amazed by it. Do you want to take some time to discuss it, explain why you built it and some of its benefits?
Yeah, absolutely, and would love to. So if you're not familiar with Signals, this is a new library that I started off by exploring. I've been in the TypeScript and JavaScript world because I was helping the Lit team for a while, and one of the things that I got to witness over there is Signals kind of
coming out, being really popular, and then a lot of people starting to integrate them. This includes Angular, SolidJS, Quick, React, you name it. If there's a JavaScript library, or in Svelte, if you name it, there's probably a JavaScript library using it. Now, there's been frameworks like Vue and a bunch of other ones that have all had signals, and signals is not a new concept by any means. But signals...
have just taken that world by storm. And if you get JavaScript frameworks to agree on anything, then there's got to be some magic going on. And so it started off by observing, making some examples. And, you know, my naive thought was, well, how is this just different than value notifier? We already have a get and set value that we can listen to reactively.
And so then I just really didn't think much of it. And it wasn't until later where some people in the community were diving into some stuff. And I got to look into some different source code. And it was way more of a straightforward example. And so I got to read through the source code in its entirety. And when I did it, I realized, wait, there's something here and I'm going to try to port it to Dart.
So I did that and it was really cool. I was I was excited, but it wasn't amazing. So that was like the very first version of Signals, which I was just calling Dart Signals. And then I was almost done with it. I was about to move on to something else. But then then I remembered that Preact had done something different with Signals.
And Preact was worked on a lot by Jason Miller, who used to also be at Google. So I remember that they had made Preact signals in such a way where a lot of frameworks could adopt it without needing to have the framework-specific features of it inside of it. And so that intrigued me. And it was a single-file implementation, which I think was also really important because it didn't have any dependencies. It was all right there in the code. And so what I did is I took my implementation,
And I started to port it to Dart and I was able to completely port it in its entirety and wrote a bunch of tests to make sure it was all working. And of course, I found some
you know, one character things that I was missing. But once I got it, it was just pretty awesome. One of the really cool things about the Preact implementation versus all of the other implementations is it uses a doubly linked list as a data structure. Almost all signals typically reach out for an array or a set to store its dependencies. And I'll go over it a
Because of this, it's able to just store a reference of its sources and targets and even get rid of signals that haven't been updated or listened to or disposed even before the garbage collector. And what that means is when the first time you run your application,
it'll pretty much stabilize really quickly on how much memory is going to be used and it'll stay that performant the rest of the time. It has a really cool mechanism for that. But yeah, anyways, so after building that, it was about bringing the Dart reactivity that I had ported in Preact to Flutter. And so the first thing I did was name the package PreactSignals.
And of course, that was really confusing for SEO because people don't know what Preact is. Preact makes no sense in Flutter land. But I wanted to be true to the implementation. Anyways, I look up the package for Signals.
and I see that it hasn't been updated in 10 years. And so I was like, oh, well, someone has the name, it's fine, whatever. And then I looked back later, like probably the next day at the GitHub repo. And lo and behold, the person that has the name and the implementation was actually someone I reported to at Google. So I messaged them and they
transferred ownership, and then of course updated the version. So that was really exciting. And then since then, I started to make the reactive side for Flutter. And this is the part where I thought was really interesting because it really started to feel like magic. I've used, I think, every possible state management out there, and I've probably shipped production apps with almost every single solution.
And if I haven't shipped it, I have explored it extensively. So I am a huge fan of seeing what the community was doing. So one of the biggest principles for me was, you know, like, well, I don't just want to build another state management library and do what everybody else is doing. I want to do something that is novel and different and really trying to save time. So, you know, a minimal API is,
One of the things that I particularly wanted to do with this is focus on writing Dart code as opposed to boilerplate or framework code. And I wanted to make a reactive system for Dart that is enhanced by Flutter, but you could use in a Dart web application, you could make a reactive CLI, you could do Dart to native, literally anything is a
a possible candidate for this reactivity. So when I started doing Flutter, I created, I started off with just an extension method called dot watch. And what it would do is it would look up it's the nearest tree and rebuild the closest element. This could be a single widget, it could be a builder. And it was really cool. But there was some cases that, you
that were needing to be covered and the community had actually started contributing to the signals repo, which I thought was really cool and people making content for it. And so one of the first things that people had done was like review like, oh, you know, this might be able to be a little bit better. So I explored building a watch widget. The watch widget is a drop in replacement for the builder widget.
And we'll allow you to, if you want just to wrap the entire widget, you can. But it offers super fine grain reactivity. And you might be thinking, well, I can already do that with a value list in WillBuilder. I can already do that with all of this. But with signals, you don't have to say which dependencies you're using. You also don't have to use them every single time.
Unlike hooks and some other state libraries, you can do them in a condition. You can react to them, you know, potentially on different branches. You can use switch pattern matching. You can have one signal or 10 signals in the builder method and much, much more. I actually built a node-based editor, which I think would be cool if you could check out. That kind of shows that you can have, like,
cycles in the graph dependencies all connect to each other but it's really powerful and and then after that i built a listen method too that is the same but it doesn't rebuild a widget just reacts with a callback but by doing this just by having these three primitives i was able to cover all of the cases that i needed to um for flutter reactivity now um
The big advantage of signals when it compares to some other systems is two really, really big things. The first part is signals is a synchronous state library. And a lot of other solutions are at best future or, but usually async. Now what this means is you will
write some values, you'll call network requests, you will have functions that call other functions, you'll have streams that get updated and all that. But your UI is rendered every frame, potentially, and needs to be synchronous. So you need to always show the correct state. But not only that, because it's a synchronous library, you can do animations with it, you can do
predictable updates because you know that there's nowhere in the graph that is going to have to wait for another signal. It's like basically running in the microtask queue. Now, and the other huge part is signals is a pull-based system, not a push one. And you may not know what that means. And so in short, if you think of like value notifier or block, for example,
When you update a value, you are triggering all the computation at the time of updating. So when you call set value, it will run over its listeners and notify them, which then if those have listeners, that'll then also propagate and update them. But this has, you know, its own advantages, but I think ultimately leads to a lot of work being done that you don't need to do.
With signals, you can update a value, a signal value, as many times as you want. You could literally update it a thousand times a second. But what's cool is computed is the other primitive of signals that allows you to reference any number of signals and return a value. Now this is a callback. And let's say you have that signal that's updating a thousand times a second. You have a computed value that listens for a condition and returns a value.
Now, this computed value could maybe only run a couple times a second or maybe even once depending on the condition. And then you could even have another chain of computed signals that listens for that. But what's really magical is if you never read the computed signal, those callbacks actually don't ever get called. And so when you think about your state in your system and of your UI state of your application,
Typically, you're going to have things like a user signal where it's going to be tied to some authentication callback and that user signal is going to be changing and updating often.
You're going to have database queries, you're going to have network requests, you're going to have conditions like whether the network is active, you're going to potentially use like, does this person have access to a paid plan, you're going to have all of these disconnected signals that are updating state at their own frequency. But then your screens are not going to necessarily just be utilities referencing every possible signal always.
You're going to be deriving state and you're like querying it of like, I want to show not all the to-dos, but a filtered set of to-dos with these values. And, you know, so often in computed allows you to describe what you want to render and as minimal things as you can. That means that, you know, it'll also cache its value. So, you know, you can read it every frame and it's not going to have to re-recompute.
And let's say you have lots of computed signals in a tree, or in a chain, rather, because it's not a tree. It'll only have to recompute its callback if its parent changes, like in its dependencies, and it doesn't have to keep propagating. And so that's really...
Really makes it really perform it. And I think that's really cool because signals is a disconnected graph. There is no root signal. There's no root tree that propagates it down. You don't have to wrap your entire application with a root widget. And it just really allows you to build almost every state primitive you can think of. There's other helpers like batch, which lets you update multiple signals in a single state.
callback effects, which is what the watch widget and listen are built on. This allows you to subscribe to a signal and trigger a callback for updates. And besides like the core signals that I did, really, I started just writing syntactic sugar for a lot of common helpers.
This includes the value signals like set signal map list, but also things like future and stream signal and async signal, which use an async state to represent all the possible states that the signal can be in. One of the biggest things that people usually ask is like, well, how do I do a async computed? And I think this is like one of the biggest misconceptions when coming to signals is,
You're not creating an asynchronous graph that you're resolving at the time of reading. You're creating a bunch of signals that represent values that change over time. You're querying that data based on that derived state. And what you should do is use effects to trigger callbacks to async functions that trigger new updates to signals and so often, or so on. And then also, you can use things like feature signals to react to values, but
Signals is synchronous, and I think that's just where the real magic is. But I know it's been tripping up some people, which, you know, it's totally fine. It's different. But yeah, I have just been really liking it. I've been starting to explore it in a lot of different ways. So I talked about the node-based editor, but it's a good example of something that I've been really wanting to build for a while, but haven't had the proper state library to build
with the you know cyclical graphs and you know things connected to each other and all being updating you know you know potentially you know thousands of times and with signals i was actually able to finally make the demo and um it's really cool because you can have signal values that uh update and then are connected in chains and i was even able to make a full adder full adder which uh is a pretty interesting logic gate and stuff like that so
Yeah. But, you know, saying that all to say is like, I think that signals also are a nice complement to other solutions that the community has. Like, for example, the first thing you may try to do is like replace all of your dependency injection with it. And while I do think it's it can be used for that, I think like I personally use get it and a lot of.
um stuff that i do and then i pass in my database providers and stuff down the tree and then i create the signals you know in the in the global or local widgets but other things like angular has been doing some really cool stuff with signals where they're using you know they've been on rxjs for a long time and their combination of signals with rxjs is actually kind of cool because um
RxJS is a good example of reacting and declaratively saying what happens to the state over time. And signals are really good for building out UI, reading values and updating values. And so I ported some of the extension methods and connectors that they had, but you should definitely check it out. But one of the really cool things that I have on the doc site is an RxDart and signals port.
where it shows how to connect them together. And I think you'll see that they're a cool companion because it allows you to write code that is really easy to react to. And I think that's the really nice part. And there's some other things that I've done, whether it be dev tools or adding things like observers and stuff like that. But really the magic comes down to how is the best way I'm going to build the state for this screen?
And what I've been finding is that signals offer those nice primitives of being able to represent all of the different types and permutations that I'm trying to do. And it can be super simple, it can be really complex, but you kind of get that performance minimal updates and caching for free. And you have you can, like I said, start with a watch around your whole widget tree, and then
If you have a sub-part of your tree that you want to create a bound for, you can just wrap that with its own watch and it'll create a boundary. But it's really, really, really, really interesting. I would highly suggest you check it out. There's a GitHub repo, github.com slash rhodydavis slash signals.dart, that you can check out a bunch of examples of.
I also have been pretty diligent on checking out the discussions. There is a lot of community feedback already and continuing to do so. So please dive in and I'm happy to hear your thoughts on stuff. And also if it's just, you know,
you're curious about JS, like why signals are so popular, why are we doing it in Flutter? That's kind of like why I'm focusing on making more content for it too. So if there's specific things you need there, please reach out to me on Twitter or wherever. But I think that there are a lot of cool opportunities to re-look at how Flutter does state updates. And, you know, state management in Flutter has been
interesting for a while but i think it's because you know there's been a lot of systems that have been able to do some really cool things on one aspect of it but then you reach a point where it's like well this part doesn't work well or this this requires too much for the plate or this is too different from what i would want to be riding um
But I know we were talking earlier, you know, there's some cool things that have led to the evolution of signals. There's things like Knockout.js. There's really old signals that were based on, you know, observables before that. Solid.js actually took a lot of that and, you know, stood on the shoulders of giants and made a really cool signals library.
um it also relied a lot on uh the framework i know i think they've been making it easier to use outside of it now but um preact took what solid did and what looked at what the rest of the community did and was able to even take the next level and i think that's why there's this evolution over time and like you know because my first thought was why is it happening now but i think uh
There's been a lot of stuff that have led to this. And because we're here now, I think it's a really cool time to... If you haven't updated your state management in a while or looking for a new solution, I would highly suggest you check it out. Because like a lot of other people have said, and including myself, I've been very...
pleasantly surprised. And it's been like a breath of fresh air for, you know, trying to build reactive state in a super minimal way without code generation or needing to extend a bunch of framework specific stuff. And I think while all of those have their purpose and are incredible, I think that being able to just write better dark code is a nice part about it.
That was an amazing explanation. Thank you so much. So just while I still have you, is there any advice you give someone starting out with Flutter who's a new developer? Absolutely. Um, one of the biggest things that helped me in my career pretty early on was, um, getting involved in, you know, whether it be, um, discord or, um, the Slack, I think they all moved to discord now, but, um,
Also finding and connecting with real people on Twitter and other platforms is really important to try to find people in the community that you can ask questions with. There's some also awesome things like hump day and the Flutter community is really great. So, you know, try to jump and talk with people. Having those connections really early on was really a nice way to
Understand that people building these libraries are real people behind the, you know, on the other side. And with that, you know, the other big part was I really like reading code.
to understand something. You know, documentation is secondary. I think that documentation and code is a really good option. So I was diving into the Flutter framework and GitHub and looking up a bunch of stuff. You'd be surprised at how many Dart and Flutter repos there are out there that just have some amazing bits of code
really cool uh examples um one of the ones i'll call out right now is uh if you've never seen the async package by the dart team it's a really cool uh example of uh just a hidden gem um or the retry package that's another one with exponential back off and stuff like that but really try to do your best to um find people uh the other thing that was useful for me was um
When I started, there weren't a lot of packages. I mean, there were still a lot, but not as many as there are now. And so for me, it was like trying to find what's there, read the source code, and try to help and contribute where I saw things were missing. I would suggest that if you are...
not like extremely new to Flutter, but recently new to Flutter, dive in and try to find if there's any packages that you love that could use some love with a pull request or just helping by small little things. Making contributions is kind of what makes Flutter amazing.
And, you know, having it be open source is a really cool way how we can all help each other and to build some cool examples. A lot of people building packages are a single person, you know, and they're probably building it because they have a production application that they want this one part that they've done a lot of times to help the community. And so you may find packages that haven't been updated in a year.
doesn't mean they're dead, but I would say, you know, it's a great time to try to, um, connect with them and to, uh, offer pull requests and trying to, you know, help move the wheel. Um, and then if there's, um, examples that you need, don't be afraid to ask for it. Um, cause there's probably people in the community that, um, would love to build it. Um,
And I would say if you are a little bit more advanced and have come from JavaScript or iOS or Android, I would highly suggest you look at building plugins for Flutter because leveraging your native code experience actually makes it a really great package. And so that was the other really big part that helped me. Nice. That's great advice. Rody, thank you so much again for being on the podcast. And thank you for listening. Until next time. Awesome. Thank you. Thank you.