From 620da3c9e3384b17ce2e0fb6b41ec519fcf350e9 Mon Sep 17 00:00:00 2001 From: Burhanuddin Rashid Date: Mon, 11 Nov 2019 16:56:25 +0530 Subject: [PATCH] 15: Build Place API and models using json_serlization --- analysis_options.yaml | 2 +- lib/pages/map/map_bloc.dart | 20 ++-- lib/pages/map/map_page.dart | 17 +-- lib/pages/places/models.dart | 136 ----------------------- lib/pages/places/places_api_service.dart | 23 ++-- lib/pages/places/places_models.dart | 120 ++++++++++++++++++++ pubspec.yaml | 3 +- 7 files changed, 158 insertions(+), 163 deletions(-) delete mode 100644 lib/pages/places/models.dart create mode 100644 lib/pages/places/places_models.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index 84426a6..3382f52 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -2,7 +2,7 @@ include: package:pedantic/analysis_options.yaml analyzer: exclude: - - lib/src/locations.g.dart + - lib/src/places_models.g.dart linter: rules: diff --git a/lib/pages/map/map_bloc.dart b/lib/pages/map/map_bloc.dart index b59223e..6e0e6e7 100644 --- a/lib/pages/map/map_bloc.dart +++ b/lib/pages/map/map_bloc.dart @@ -1,13 +1,13 @@ import 'dart:async'; import 'package:flutter_app/bloc/bloc_provider.dart'; -import 'package:flutter_app/pages/places/models.dart'; import 'package:flutter_app/pages/places/places_api_service.dart'; +import 'package:flutter_app/pages/places/places_models.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; class MapBloc extends BlocBase { MapBloc(this.placesApiService) { - _fetchLocations(); + _fetchLocations("Mumbai"); } final PlacesApiService placesApiService; @@ -17,10 +17,10 @@ class MapBloc extends BlocBase { Stream get mayType => _mapTypeController.stream; - StreamController> _officesController = - StreamController>.broadcast(); + StreamController> _officesController = + StreamController>.broadcast(); - Stream> get offices => _officesController.stream; + Stream> get offices => _officesController.stream; @override void dispose() { @@ -32,14 +32,14 @@ class MapBloc extends BlocBase { _mapTypeController.sink.add(mayType); } - void _fetchLocations() { - placesApiService.getGoogleOffices().then((value) { - _officesController.sink.add(value.offices); + void _fetchLocations(String placeQuery) { + placesApiService.searchPlaces(placeQuery).then((value) { + _officesController.sink.add(value.candidates); }); } } -extension MyOffices on Office { +/*extension MyOffices on Office { Marker toMarker() { return Marker( markerId: MarkerId(name), @@ -50,4 +50,4 @@ extension MyOffices on Office { ), ); } -} +}*/ diff --git a/lib/pages/map/map_page.dart b/lib/pages/map/map_page.dart index cf404c7..2122293 100644 --- a/lib/pages/map/map_page.dart +++ b/lib/pages/map/map_page.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_app/bloc/bloc_provider.dart'; import 'package:flutter_app/pages/map/map_bloc.dart'; -import 'package:flutter_app/pages/places/models.dart'; +import 'package:flutter_app/pages/places/places_models.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; class MapPage extends StatelessWidget { @@ -48,7 +48,7 @@ class MapPage extends StatelessWidget { }, ), //TODO: Fix the scroll and item are not visible - StreamBuilder>( + StreamBuilder>( stream: mapBloc.offices, builder: (context, snapshot) { return ListView.builder( @@ -56,15 +56,18 @@ class MapPage extends StatelessWidget { itemCount: snapshot.data.length, itemBuilder: (context, index) { var item = snapshot.data[index]; - return ListTile( + /*return ListTile( leading: CircleAvatar( backgroundColor: Colors.red, child: Text("P"), ), title: Text(item.name), - subtitle: Text(item.address), + subtitle: Text(item.name), + );*/ + return Text( + item.name, + style: Theme.of(context).textTheme.headline, ); - //return Text(item.name); }, ); }, @@ -74,13 +77,13 @@ class MapPage extends StatelessWidget { ); } - Set buildMarkerSet(List offices) { + /*Set buildMarkerSet(List offices) { Set markers = Set(); for (var office in offices) { markers.add(office.toMarker()); } return markers; - } + }*/ CameraPosition buildInitialCamera() { return CameraPosition( diff --git a/lib/pages/places/models.dart b/lib/pages/places/models.dart deleted file mode 100644 index 1b78e41..0000000 --- a/lib/pages/places/models.dart +++ /dev/null @@ -1,136 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; - -@JsonSerializable() -class Locations { - Locations({this.offices, this.regions}); - - factory Locations.fromJson(Map json) { - return Locations( - offices: json['offices'] != null - ? (json['offices'] as List).map((i) => Office.fromJson(i)).toList() - : null, - regions: json['regions'] != null - ? (json['regions'] as List).map((i) => Region.fromJson(i)).toList() - : null, - ); - } - - List offices; - - List regions; - - Map toJson() { - final Map data = Map(); - if (this.offices != null) { - data['offices'] = this.offices.map((v) => v.toJson()).toList(); - } - if (this.regions != null) { - data['regions'] = this.regions.map((v) => v.toJson()).toList(); - } - return data; - } -} - -@JsonSerializable() -class Region { - Region({this.coords, this.id, this.name, this.zoom}); - - factory Region.fromJson(Map json) { - return Region( - coords: json['coords'] != null ? Coords.fromJson(json['coords']) : null, - id: json['id'], - name: json['name'], - zoom: json['zoom'], - ); - } - - Coords coords; - String id; - - String name; - - double zoom; - - Map toJson() { - final Map data = Map(); - data['id'] = this.id; - data['name'] = this.name; - data['zoom'] = this.zoom; - if (this.coords != null) { - data['coords'] = this.coords.toJson(); - } - return data; - } -} - -@JsonSerializable() -class Coords { - Coords({this.lat, this.lng}); - - factory Coords.fromJson(Map json) { - return Coords( - lat: json['lat'], - lng: json['lng'], - ); - } - - double lat; - - double lng; - - Map toJson() { - final Map data = Map(); - data['lat'] = this.lat; - data['lng'] = this.lng; - return data; - } -} - -@JsonSerializable() -class Office { - Office( - {this.address, - this.id, - this.image, - this.lat, - this.lng, - this.name, - this.phone, - this.region}); - - factory Office.fromJson(Map json) { - return Office( - address: json['address'], - id: json['id'], - image: json['image'], - lat: json['lat'], - lng: json['lng'], - name: json['name'], - phone: json['phone'], - region: json['region'], - ); - } - - String address; - String id; - String image; - double lat; - double lng; - String name; - String phone; - - String region; - - Map toJson() { - final Map data = Map(); - data['address'] = this.address; - data['id'] = this.id; - data['image'] = this.image; - data['lat'] = this.lat; - data['lng'] = this.lng; - data['name'] = this.name; - data['phone'] = this.phone; - data['region'] = this.region; - return data; - } -} diff --git a/lib/pages/places/places_api_service.dart b/lib/pages/places/places_api_service.dart index 510b2eb..169c5e2 100644 --- a/lib/pages/places/places_api_service.dart +++ b/lib/pages/places/places_api_service.dart @@ -1,23 +1,30 @@ import 'dart:convert'; import 'dart:io'; +import 'package:flutter_app/pages/places/places_models.dart'; import 'package:http/http.dart' as http; -import 'package:flutter_app/pages/places/models.dart'; +// ignore: constant_identifier_names +const BASE_URL = "https://maps.googleapis.com/maps/api/place"; +// ignore: constant_identifier_names +const API_KEY = "YOUR_PLACES_KEY_HERE"; +// ignore: constant_identifier_names +const PLACE_PARAMS = + "/findplacefromtext/json?key=$API_KEY&inputtype=textquery&fields=photos,formatted_address,name,geometry&&input="; +// ignore: constant_identifier_names +const SEARCH_PLACE_ENDPOINT = BASE_URL + PLACE_PARAMS; class PlacesApiService { - Future getGoogleOffices() async { - const googleLocationsURL = - 'https://about.google/static/data/locations.json'; - + Future searchPlaces(String placeQuery) async { + final googlePlacesURL = SEARCH_PLACE_ENDPOINT + placeQuery; // Retrieve the locations of Google offices - final response = await http.get(googleLocationsURL); + final response = await http.get(googlePlacesURL); if (response.statusCode == 200) { - return Locations.fromJson(json.decode(response.body)); + return PlaceResponse.fromJson(json.decode(response.body)); } else { throw HttpException( 'Unexpected status code ${response.statusCode}:' ' ${response.reasonPhrase}', - uri: Uri.parse(googleLocationsURL)); + uri: Uri.parse(googlePlacesURL)); } } } diff --git a/lib/pages/places/places_models.dart b/lib/pages/places/places_models.dart new file mode 100644 index 0000000..e79af1e --- /dev/null +++ b/lib/pages/places/places_models.dart @@ -0,0 +1,120 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'places_models.g.dart'; + +@JsonSerializable() +class PlaceResponse { + PlaceResponse({this.candidates, this.status}); + + factory PlaceResponse.fromJson(Map json) => + _$PlaceResponseFromJson(json); + + final List candidates; + + final String status; + + Map toJson() => _$PlaceResponseToJson(this); +} + +@JsonSerializable() +class Candidate { + Candidate({this.formatted_address, this.geometry, this.name, this.photos}); + + factory Candidate.fromJson(Map json) => + _$CandidateFromJson(json); + + final String formatted_address; + final Geometry geometry; + + final String name; + + final List photos; + + Map toJson() => _$CandidateToJson(this); +} + +@JsonSerializable() +class Geometry { + Geometry({this.location, this.viewport}); + + factory Geometry.fromJson(Map json) => + _$GeometryFromJson(json); + + final Location location; + final Viewport viewport; + + Map toJson() => _$GeometryToJson(this); +} + +@JsonSerializable() +class Location { + Location({this.lat, this.lng}); + + factory Location.fromJson(Map json) => + _$LocationFromJson(json); + + final double lat; + final double lng; + + Map toJson() => _$LocationToJson(this); +} + +@JsonSerializable() +class Viewport { + Viewport({this.northeast, this.southwest}); + + factory Viewport.fromJson(Map json) => + _$ViewportFromJson(json); + + final Northeast northeast; + + final Southwest southwest; + + Map toJson() => _$ViewportToJson(this); +} + +@JsonSerializable() +class Northeast { + Northeast({this.lat, this.lng}); + + factory Northeast.fromJson(Map json) => + _$NortheastFromJson(json); + + final double lat; + + final double lng; + + Map toJson() => _$NortheastToJson(this); +} + +@JsonSerializable() +class Southwest { + Southwest({this.lat, this.lng}); + + factory Southwest.fromJson(Map json) => + _$SouthwestFromJson(json); + + final double lat; + + final double lng; + + Map toJson() => _$SouthwestToJson(this); +} + +@JsonSerializable() +class Photo { + Photo( + {this.height, this.html_attributions, this.photo_reference, this.width}); + + factory Photo.fromJson(Map json) => _$PhotoFromJson(json); + + final int height; + + final List html_attributions; + + final String photo_reference; + + final int width; + + Map toJson() => _$PhotoToJson(this); +} diff --git a/pubspec.yaml b/pubspec.yaml index d27d759..b9028d4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,11 +14,12 @@ dependencies: rxdart: ^0.19.0 google_maps_flutter: ^0.5.21+8 http: ^0.12.0+1 - json_serializable: ^2.0.2 + json_annotation: ^3.0.0 dev_dependencies: pedantic: ^1.4.0 build_runner: ^1.2.7 + json_serializable: ^3.0.0 flutter_test: sdk: flutter