Google Map with Places Autocomplete in Flutter, Part 3

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody welcome back to the channel and this series on flutter google maps with auto complete uh when we left it last time we actually left it here if you noticed we were functioning with the hot reload but as soon as i restarted i got an error and that is because on the home screen when we created our containers to layer on top of the map we created uh the search list and we put a conditional argument on the dark portion of the screen that you see there as a background but nothing on the list i said i was going to do it in the video and then i never did so uh if you come in your build method in your scaffold and you may have already figured all this out but inside the stack we have three containers we have the map we have the dark box and we stuck an if statement in front of it and then we have the list builder and so i'm just going to copy that statement and also stick it in front of the list builder so that if we don't have any search results we're not trying to check the length of it and that will resolve it right there also i noticed i did run this on my iphone but when i went to run it on the new simulators you get with xcode at least mine is not pre-loaded with a location by default so i had to go to features location custom location and set a location uh otherwise it was just going to spin and spin and spin indefinitely so i did have to do that it doesn't happen on a phone but with the emulator you do have to give it a location before it's going to uh to tune into it all right so where we left this last time we are able to search locations and we're able to pick them but nothing happens when we pick them and what we want to do is fix it so that when we click on the location the map is going to take us to that location automatically so that's going to be our task today and then in the fourth episode we will hit on these filters here uh that uh find the nearest location and then zoom in or zoom out appropriately so that the bounds auto adjust that will be part four but in part three we're just going to hook up this part where we pick a location and the map responds to it so to make that happen what we're going to need to do is we're going to need to add a map controller we don't have one yet uh and the google maps in flutter the way it works it will load up with some pre-configured values but if you want to change the map afterwards you need to have a controller and do that through the controller so we'll add a map controller to our widget we're going to go back to our places service and when we are getting results here we're getting a places id and so we want to hook up our places service to be able to pass that places id back to the google places api and get some details on that place including the coordinates of the place when we get that back from the api we're going to want to dump that into a stream that we can listen to on our home page here so we'll create a model to get our place results we will create a service to go out there and get those uh and then we'll create the stream to listen on that and then we will create a function that will tell our controller that we have a new location and we want it to to go ahead and do that then lastly we will just wire up the function so that when we click on one of these list tiles it's called and then we'll put a stream here on our home page uh that we can listen to that response and then we'll just put a stream listener on our widget so that it is aware that a change has taken place in our block and can respond accordingly all right so that's our task and so the first thing i said is we're going to add a map controller so here on the home screen dot dart page we can come all the way up above the build function and inside of our state object let's go ahead and add a completer of type google map controller and we'll call that underscore map controller and we will set that equal to a new instance of a completer and looks like we'll need to import that from dart async so with that in place with our map controller we can come down to the bottom and write ourselves a function so that when we get a new location we will have a function ready to to take that controller pass the new location to it and have the map respond so we can come outside of our build method inside of our class so right in right before the last closing curly brace we can give ourselves a function and that's going to be a future and it's a void we're going to do all our controls through the controller so we don't actually have to return anything from this function we can call it go to place and we can add in a place we don't actually have a place model yet so don't worry about the error there but let's make it asynchronous and what we need to do to get our google map controller is to say we're going to have a final google map controller and we'll call it controller lowercase and what we'll do is a weight map controller dot future all right and once we have this controller object we can use it to control the map and so one of our options is to animate the camera so that will take a camera update dot new camera position and this will take a camera position object which has a target which is a lat lng and in here we will pass uh you know what let's hold off on actually passing that in there because we're gonna pass in some properties from our place object tell you what let's just do 35.0 and 75.0 and let's remember to come back and then outside of that target will be zoom property and we'll just set that at 14. you can set that at whatever you want all right so maybe it would have been better to do our place model first but let's do that now so we have in our models folder we model the search results which is the results of our autocomplete so in the google maps documentation or the places documentation we got responses for autocomplete and remember this is all part of google places api the next one we're actually going to want to hit is the details so the autocomplete gives us an id for a place but it doesn't give us the geographic coordinates but if we have the id the easiest way to get all that information is to use the places details api and so this is our url here um it's got output here so you need to specify whether you want json or xml and then the parameters are well the ones that are required are key and places id there's some language regions etc we're not going to use those unless that uh suits your purpose so if i put that into postman and just get a an idea of what our response is going to look like we can start to model this up by picking out the fields we want so for output i'm going to want json and then for my parameters so we said we want a key and we're also going to want a place id that's what they said in the document there yeah underscore so the key i'm going to grab on my you can grab it from your google console but i do know i have it here in services in places service so i'll just grab that there key equals that and place id actually you know what i think i'm gonna i don't have one but let's flip to the documentation um and i'm gonna go a little further down here and i see they have an example here with a place id so i'm just gonna use that one alright so if i send that so i get address components not really interested in that uh let's see i get geometry and geometry has a location which has my latitude and longitude so i want the location object i want the geometry object um i think i also want well there's a lot there um i think i'll also grab vicinity just because that has uh just kind of a nice friendly label of where that is um and is our name property too yeah there's also a name property so i'll just grab name vicinity and location so we're gonna have to do is model the location object model the geometry object and then we can attach those to our main place object you could get fancy here and try to flatten this model but i prefer to just model those out myself so we come into the models folder i like to start on the inside and work my way out so i'm going to create a model for a location object so i will add and i'm going to call that location and pretty simple modeling here was going to create class location and our two fields are lat and lunge that is my dog he's a very loud sleeper he's confined to my office because he's eaten everything we've owned which we've thought and we'll do a factory constructor down here once he ate all our possessions we'd be set but he started eating the carpeting now so we'll do location from json map dynamic dynamic parsed json like that and anytime you are dealing with embedded json you're better off just to go dynamic dynamic it seems to recognize that better when you start to pass objects inside of another and so here we'll just return location object and we'll build one from our results so the parse.json lats and i just look in here at this so i know i'm going to get this location object i'm going to have a lat and lng property so we'll use those all right locations all set so working from the inside out so i've got location now i need geometry and that's another simple model so we'll create a new object in there called geometry and this one's even even simpler than location because all we want is well we got to get our class there geometry and all we want is the location so we will get the location make sure i import that location type from my models and then just cover my constructor so a name constructor with this dot location and then geometry dot from json map dynamic dynamic parse json and we'll get a geometry object i want to return that and the location will be parsed json location and i should have a factory keyword front of there and then we're all set all right so we've modeled from the inside out we've modeled our location we've modeled our geometry now we're at the high level so we can go ahead and grab geometry we can grab the name property and we can grab vicinity so one more model and this one will be called place so we've got place search and now we'll just have place class place and we'll take in geometry which we'll call geometry final string will be our name final string vicinity place and so this dot geometry well order doesn't matter take them as they come and then a factory constructor so factory place from json and that will be a map here we can go ahead and put a string because we're at the top level for our key value keep the values dynamic we'll do parse json and we'll return a place so geometry and this is uh we're going to do geometry from json geometry and i'm feeling like i made a mistake in that last model so i'll circle back to it so this is formatted address will be our name so let's see i'm looking at my source code and i must have decided that i liked this better than the actual name property for the name there goes the dog again he's whistling now so i guess i'm going to grab that if you want to grab a different property you can but i'm going to map this formatted address to vicinity getting to that age where the decisions i made three days ago or a week ago are just foreign to me logic for why they why they came about forget about it that's the dog again all right so we got that there and then i was paranoid that i'd done geometry wrong and sure enough i did i actually needed to come outside of this and cast this to a location object so location from json and then put that inside parentheses there okay all right all done modeling so let's come out to our home screen here and now that we have a place object i can just import that get rid of the error and before i forget let's do place dot uh let's see we just did this place dot so we go into our geometry object then we can go to our location and then off of that we can grab latitude and then our model will be placed placed.geometry.location of course and then lng here all right so that function is all set to be called alright so let's revisit our places service and remember we did model place a search in place separately but we said place of service is all going to be one service because it's all really going to the same place and so i think what i'm going to do is just copy this one here save ourselves a little bit of time and what we're going to call this one is get place so this is going to have a place id and then we're just gonna go use that model and this call we just mocked up here in postman to go get it so what's coming in here is string place id and we're not getting a place search result we're going to get actually just a place so let's get rid of the list part 2. so that should be future of type place we'll need to import place and you notice i am using intellij i know i started this in visual studio code i'm getting tired of all the pop-ups that come up in visual studio code i think it makes very hard for people to see uh what i'm doing and i've liked intellij so i'm working with that here hopefully that's not a distraction for you so our url i'm gonna go back to postman and i'm gonna grab what i put in for a mock-up here all right and i have my key up here so where it says key i can get rid of that up to the ampersand and do key and then my place id i can replace with whatever i'm passing in here so i will get a response i will decode that into json a little different action here because we don't want to cast this as a list so for our json result let's go ahead and get the result object and so this is just i'm just grabbing this based on what i got here so i'm actually getting an html attributions array that has nothing in it and this result property has everything i'm interested in so i'm grabbing that specifically from the results or the bot the response body and i'm just going to cast that to a map string dynamic and i don't need to map through the results because i'm not cycling through a list so i can just do place from json and pass in json result and because we've modeled the i guess we'll call that result uh because there's only one and because we've modeled the fields that we want it's just going to pick off the ones we want and return those to us and leave everything else on the table okay so we can definitely get our place here uh and what we want to do to to communicate that to the view is set up a stream set up a function that will feed a stream that we can listen to on this homepage here so i'm going to go to blocks and i'm going to go to our application block and up here in my variables i'm going to create a stream controller called selected location that i can dump that location into when i get my future back so stream controller place and we'll call it selected location and we will set that equal to a stream controller of type place and just be a new stream controller i do need to bring in place i can see a warning up here that i'm opening up a stream and not closing it so let's write myself a dispose method down here and we will do selected location close like that actually that is a uh override class of change notifier so let me just call that so i get the super dot dispose and then in here i will do selected location that close like that and you know what before i forget i do need to call this at some place so let me come out to the home screen here and let's come up to the top and let's create a dispose method here so when the widget gets disposed that's when we'll call the provider as dispose method so we just make sure all those streams get disposed so let me do a final application block i think i'll just copy it from here and because i'm doing it in a dispose method as opposed to a build i do need to make sure that i set listen to false and then that will give me access to the application block and i can say application block dot dispose and then we just make sure that those streams are actually taken care of all right so back into the application block let's come down below search places and let's create a function that we can call from the view that will trigger that whole chain of events that we just have set up where it will get the place id off of this selection that we've made whichever one we click on pass it to the back end service and uh and then update the stream when it gets a response so we'll call that set selected location it will be a string and we will be able to give it a place id off of our list view it'll be asynchronous and what we can do is due to our selected location stream we can add the awaited value of places service get place and pass in our place id like that and then we will want to notify our listeners okay so with that function in place let's go ahead and flip over to our screen our home screen and let's call that whenever anybody clicks on one of these tiles so home screen we've got our list view here for search location we've got our list view builder down here which is our container which has these options on it we've got our list tile and inside of our list tile we can now add an ontap method so parentheses open up a block and what we're going to do is application block dot set selected location so that function we just created and inside of there we want to pass application block dot search results bracket index so our current record on the list view builder and the property we're looking for is place id and so if we tap that don't expect anything to happen unless you go to the places service and you put in a break point you can then see that that call is being made and our last step home screen uh is to actually notify the map and call this function down here to move that uh camera position around and actually i think we need to make this all disappear too so to the tackle the first part make the camera position uh move to the place that we've just selected we're going to want to set up a stream listener up here at the top uh let's see we've got our dispose method here let's come up above that and do an init state method and we want to bring in our application block so i'm just going to copy what we got here from dispose like that and so we want application block dot selected location dot stream dot listen so that's the stream that we're dumping into when we call set selected location after the future resolves uh let's call it not an event but a place and if the place is not equal to null then we will use our go to place function and pass in that place all right so that's a subscription to a stream so we should dispose of that so if i come up here uh below the completer the the map controller i'm going to create a stream subscription for location subscription and i'll set that equal to the listener we just set up and then in dispose i can get rid of it so i can do subscription.cancel like that all right and so with that in place we should be pretty close to having the camera shift uh one little step here though we do need to connect the map controller to the map uh so let's go down to our container google map and after our zoom let's say on map created we're going to pass in a google map controller and we'll call it controller open up a code block and in here we can do map controller dot complete controller all right and with that i believe if we want to go to sandusky ohio and we click on that let's do a hot restart and there it goes all right so as uh as i suspected we do need to get rid of uh this uh overlay and the words uh but the map is doing what it should do so we do have a uh condition here on our overlay elements and one of them is if the search result is not equal to null then it will show so if we come back to our application block and we find our set selected location and inside there we just say search results equals null then the notify listeners will update our ui we should be able let's select somewhere different to go to sandwich massachusetts sounds delicious and have that disappear all right so wherever we want to go we should be able to search it select it what is sdl germany and it will take us to that spot all right so that's going to wrap this episode in the next episode we're going to finish off this app by adding this step where after we're taken to a location we are able to uh select a chip down here and find the nearest one of those items whether it's a pet store pharmacy locksmith whatever so we're going to tap into google places and the types and then we're going to find those we're going to automatically adjust the bounds of the map depending on the results uh so it will it will uh scan in or out depending on where we select it looks like i've got this demo app stopped so it's not gonna do it for us but you've seen it before and so that will be the uh fourth and final episode of this series hope to see you then thanks for watching
Info
Channel: Andy Julow
Views: 5,886
Rating: undefined out of 5
Keywords:
Id: 1UJJGb86_1g
Channel Id: undefined
Length: 33min 41sec (2021 seconds)
Published: Wed Feb 24 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.