Flutter Provider - Advanced Firebase Data Management

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Good work! I'm gonna check out all your stuff this weekend. This is precisely the type of content I've been looking for

👍︎︎ 7 👤︎︎ u/chris37879 📅︎︎ May 17 2019 🗫︎ replies
Captions
[Music] one of the most challenging aspects of building an interactive app is controlling the flow of data that's why you might often hear developers debate over best practices around state management and while flutter and firebase both provide some awesome tools to work with reactive real-time data it's still not easy in today's video I want to show you some of my favorite patterns for apps that have complex data flow needs with things like firebase authentic cited to show you how a library called provider can dramatically reduce the complexity of your code if you're new here like and subscribe and you can find the full source code on fire ship i/o and I should also mention that I just recently released my own flutter app on iOS and Android it allows you to take quizzes along with my youtube videos as well as my full flutter course which was just released a couple days ago part of the course is free but consider becoming a pro member to get the full experience now when it comes to state management with flutter and firebase I've tried a whole bunch of different approaches and there are a lot of different solutions that work so it often just comes down to the developers preference so let me give you an idea of some of the things that I really value on the subject first I want a good separation of concerns from the business logic and presentation logic in other words I don't want to have a whole bunch of logic related to the retrieval of data embedded somewhere in the widget tree the second thing I value is being able to share data easily throughout the widget tree I might need to access my firebase user in 10 different screens and I definitely don't want to be listening to a stream manually in 10 different state full widgets and third I like to try to avoid boilerplate code there's a lot of really good and popular state management solutions out there but they tend to require a lot of configuration and in most cases I just prefer to have simple conventions over explicit configuration now the provider package for flutter does a really good job of meeting my needs and all three of these areas and all it really does is provides syntactic sugar for inherited widget as well as some other low-level building blocks and flutter like stream builder and change notifier it allows you to expose a value or as we'll see in this video a stream and then access the value in any of the descendant widgets as simple as that sounds it actually leads to some very profound benefits especially when you need to compose multiple streams together for example the firebase user with some related data in the database we can demonstrate that in the simple demo where the user logs in and then they can create a record in the database related to their user ID and then they can add additional documents in a sub collection to that root document now before we get into the actual source code I want to first show you some of the challenges that you might face when working with firebase and flutter so firebase exposes streams for both user authentication and firestore and the most painful way to manage those streams is manually in your own stateful widget so first of all we have quite a bit of boilerplate here just to get the staple widget set up and then we need to set a property for the stream subscription and then also the data that we eventually want to show in the UI when the widget is first initialized we'll go ahead and subscribe to our stream and then we'll call set state to update the data whenever emits a new value this is a stream to read data from buyer store and so it could cost money and it could also be sending a lot of data downstream so we need to make sure to dispose of it when this widget is no longer needed that means we need to call a subscription cancel in our dispose lifecycle hood now finally we can go down here to our build method and display the data and notice how we're using bracket notation to call the title key on a map so this data is dynamic but the text widget requires a string as its argument so if the database returns null then our text widget is going to fail so we have no type safety here and dart is not very forgiving when it comes to types because it does runtime type checking now we can already make a huge improvement to this code by refactoring everything into a stream builder so this time you can see here I have a stateless widget and now I'm going to wrap our code in this stream builder and just a side note you can always do that with the refactor tool in vs code which is a huge time-saver now the stream builder widget takes a stream as its argument and it will automatically subscribe to the stream then give us access to the data inside this builder function in addition it will cancel the subscription automatically when this widget is removed from the tree now we still don't have any type safety on the data payload so oftentimes what you'll do is use double question marks here to make sure that it always returns a default value with the proper type the stream builder is awesome but what if we also need access to the user inside of the build method that's also a stream so what will most likely do is wrap this in another stream builder although we could map everything together into a single stream but that's also not exactly easy as your app becomes more complex you might need the data from multiple streams at the same time and you might have one stream that depends on another stream it's very common for a fire store document reads who depend on the currently logged in user stream and then you might need that data in a deeply nested widget and the only way to get that data down is to pass the properties down through all the children so now that we have a good understanding of the problem let's take a look at how provider solves it if you remember I mentioned earlier that provider is syntactic sugar for inherited widget so that means we can use it the same way we might use a theme in flutter where we set up our data at one point and then we use it in a child and that child will look up the widget tree until it finds the first instance of that type and use that as the data source now we're only going to be focused on streams in this video because that's the way firebase returns real-time data but keep in mind provider can also handle just regular values in your app as you can see here I'm in the root of the application and I'm going to wrap my material app in a multi provider multi provider is really convenient because it allows you to setup multiple streams or multiple values and then share them without having to nest widgets you just add all the values you want to share into a list one thing you might want to do if you use firebase authentication is observe the current user throughout the entire application we can do that by setting up a stream provider here and you'll notice that it's types to the firebase user type which comes from firebase and then we pass it the stream that actually contains that data now the real magic of this approach is that we can now treat the firebase user as if it were a synchronous value throughout the entire app if we go down here to the stateless widget we can just access the user directly inside the build method by calling provider of context with the firebase user type so now anytime we want to access the user we can do it with a single line of code without needing to set up a stream builder so we can determine if the user is logged in or not by seeing if the user object is null and then I want to take a second here to show you a cool trick in dart 2.3 you'll notice we're using conditional logic directly in the children list for the column and then we can also combine this with the new spread syntax to create a partial list that will only be visible to the logged in user so basically we're saying if the users logged in show this list of widgets but if the user is not logged in show this list of widgets so it's bold concise and readable and that already gives us a fully functioning authentication system the user logs in and the app automatically reacts because that widget that depends on the user from the provide we'll rerender when it emits a new value so it makes the user authentication just work like magic but it's a little more tricky when we start talking about fire store because fire store always returns data as a map and unlike typescript we can't just apply an interface to a map and dart so that means we need a way to deserialize our data from a map into an actual dart class so what we'll do here is just define a couple of classes that define the shape of the data this is going to benefit us in several ways it's going to give us intellisense when we're actually working with these data models in our code and it's also going to ensure that we have appropriate defaults with the proper data type like I mentioned before if you pass a text widget anything other than a string it's going to fail but writing a data model like this will help you alleviate that problem and give you a single source of truth to manage it right now we just have two immutable classes that do nothing more than instantiate some properties but what I want to show you now is how to deserialize this data from either a map or a fire stored document when you use a map it's a little more flexible because you can also use it to deserialize regular json data or some other data source like maybe from dart HTTP this from map constructor will take the map that we get from fires store as its argument then it will simply take the values on that map and set them as properties on this class and we can also use double question marks here to set some default values now this process is kind of tedious but it does give your data a strong schema and it makes working with data in your widgets a lot more user friendly mostly because you have intellisense on everything and you have some confidence that you're going to be passing the right data types to your widgets at runtime if you want to make your constructor a little more specialized you might name it from fire store and instead pass it the document snapshot this way you have access to the document ID which can be useful when working with collections because you don't automatically have the ID in the return data but the drawback here is that your constructor is now more specialized so wouldn't work with other things like just plain JSON and just to make this clear your data model should match what you have in fires store so here we have a hit points value which is a number and then a couple of strings so the data model is only responsible for creating an instance with the proper data shape what we'll do now is define a database service which is responsible for the actual business logic of retrieving these items from the database and deserializing them to the appropriate class this is just a plain dark class and I would recommend keeping this class stateless and have it focused on exposing methods that return data to you for example if we want to get one of the hero documents typed to the superhero class we can make a reference to the heroes collection with the document ID and then we can return a superhero instance with the front map constructor with the snapshot data now when we perform this read from the database instead of getting a dynamic map we'll get an actual class instance of superhero but we actually want to listen to this document as a real-time stream so we'll use the map operator on a stream to map that to an instance of the superhero now we can also do this with a list for example we want to make a query to firestore for a list of weapon documents this code is a little more challenging because we're being returned with a list of snapshots then we need to take that list and then map each item in the list down to the instance that we want which is a weapon now I'd recommend doing other things in your database service as well like performing writes to the database but the general idea here is that you're taking all of the business logic of working with a database outside of your widget tree now that we have all this setup done we can see the true power of provider in our code now we already have access to the current user in our widget so we can easily use it to create related streams by simply passing that value as an argument to our database service for this part of the UI I'm just using stream builder so that's still super convenient and in this case that will give us access to the hero document that's related to that user ID but with the provider package we can also use a stream provider elsewhere in the widget tree this is especially useful if you have your widgets broken down into a lot of small pieces of UI because it means you can use your data in all of those widgets without having to pass in the properties manually and you also don't have to create any additional stream builders or subscriptions to the stream all the data is just there and ready for you to use I'm gonna go ahead and wrap things up there if this video helped you please like and subscribe and if you want to go into even more advanced concepts than this consider enrolling in the full course on fighter ship il thanks for watching and I will talk to you soon [Music] [Music]
Info
Channel: Fireship
Views: 107,889
Rating: 4.9320154 out of 5
Keywords: app development, lesson, tutorial, flutter, ios, android, flutter provider, firebase, firestore, firebase auth, flutter state management, flutterfire, flutter firebase, stream builder, statefulwidget, firestore flutter, deserialization, dart, dart 2.3
Id: vFxk_KJCqgk
Channel Id: undefined
Length: 11min 8sec (668 seconds)
Published: Fri May 17 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.