mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 22:09:06 +00:00
[place_tracker] ChangeNotifierProvider for state management (#424)
This commit is contained in:
@@ -1,67 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class _AppModelScope<T> extends InheritedWidget {
|
|
||||||
const _AppModelScope({
|
|
||||||
Key key,
|
|
||||||
this.appModelState,
|
|
||||||
Widget child,
|
|
||||||
}) : super(key: key, child: child);
|
|
||||||
|
|
||||||
final _AppModelState<T> appModelState;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool updateShouldNotify(_AppModelScope oldWidget) => true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AppModel<T> extends StatefulWidget {
|
|
||||||
AppModel({
|
|
||||||
Key key,
|
|
||||||
@required this.initialState,
|
|
||||||
this.child,
|
|
||||||
}) : assert(initialState != null),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
final T initialState;
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
@override
|
|
||||||
_AppModelState<T> createState() => _AppModelState<T>();
|
|
||||||
|
|
||||||
static T of<T>(BuildContext context) {
|
|
||||||
final scope =
|
|
||||||
context.dependOnInheritedWidgetOfExactType<_AppModelScope<T>>();
|
|
||||||
return scope.appModelState.currentState;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update<T>(BuildContext context, T newState) {
|
|
||||||
final scope =
|
|
||||||
context.dependOnInheritedWidgetOfExactType<_AppModelScope<T>>();
|
|
||||||
scope.appModelState.updateState(newState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AppModelState<T> extends State<AppModel<T>> {
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
currentState = widget.initialState;
|
|
||||||
}
|
|
||||||
|
|
||||||
T currentState;
|
|
||||||
|
|
||||||
void updateState(T newState) {
|
|
||||||
if (newState != currentState) {
|
|
||||||
setState(() {
|
|
||||||
currentState = newState;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return _AppModelScope<T>(
|
|
||||||
appModelState: this,
|
|
||||||
child: widget.child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'place_tracker_app.dart';
|
import 'place_tracker_app.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(PlaceTrackerApp());
|
runApp(ChangeNotifierProvider(
|
||||||
|
create: (context) => AppState(),
|
||||||
|
child: PlaceTrackerApp(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class Place {
|
|||||||
final int starRating;
|
final int starRating;
|
||||||
|
|
||||||
double get latitude => latLng.latitude;
|
double get latitude => latLng.latitude;
|
||||||
|
|
||||||
double get longitude => latLng.longitude;
|
double get longitude => latLng.longitude;
|
||||||
|
|
||||||
Place copyWith({
|
Place copyWith({
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'place.dart';
|
import 'place.dart';
|
||||||
import 'place_details.dart';
|
import 'place_details.dart';
|
||||||
@@ -16,24 +17,27 @@ class PlaceListState extends State<PlaceList> {
|
|||||||
|
|
||||||
void _onCategoryChanged(PlaceCategory newCategory) {
|
void _onCategoryChanged(PlaceCategory newCategory) {
|
||||||
_scrollController.jumpTo(0.0);
|
_scrollController.jumpTo(0.0);
|
||||||
AppState.updateWith(context, selectedCategory: newCategory);
|
Provider.of<AppState>(context, listen: false)
|
||||||
|
.setSelectedCategory(newCategory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onPlaceChanged(Place value) {
|
void _onPlaceChanged(Place value) {
|
||||||
// Replace the place with the modified version.
|
// Replace the place with the modified version.
|
||||||
final newPlaces = List<Place>.from(AppState.of(context).places);
|
final newPlaces =
|
||||||
|
List<Place>.from(Provider.of<AppState>(context, listen: false).places);
|
||||||
final index = newPlaces.indexWhere((place) => place.id == value.id);
|
final index = newPlaces.indexWhere((place) => place.id == value.id);
|
||||||
newPlaces[index] = value;
|
newPlaces[index] = value;
|
||||||
|
|
||||||
AppState.updateWith(context, places: newPlaces);
|
Provider.of<AppState>(context, listen: false).setPlaces(newPlaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var state = Provider.of<AppState>(context);
|
||||||
return Column(
|
return Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
_ListCategoryButtonBar(
|
_ListCategoryButtonBar(
|
||||||
selectedCategory: AppState.of(context).selectedCategory,
|
selectedCategory: state.selectedCategory,
|
||||||
onCategoryChanged: (value) => _onCategoryChanged(value),
|
onCategoryChanged: (value) => _onCategoryChanged(value),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -41,10 +45,8 @@ class PlaceListState extends State<PlaceList> {
|
|||||||
padding: const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 8.0),
|
padding: const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 8.0),
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
children: AppState.of(context)
|
children: state.places
|
||||||
.places
|
.where((place) => place.category == state.selectedCategory)
|
||||||
.where((place) =>
|
|
||||||
place.category == AppState.of(context).selectedCategory)
|
|
||||||
.map((place) => _PlaceListTile(
|
.map((place) => _PlaceListTile(
|
||||||
place: place,
|
place: place,
|
||||||
onPlaceChanged: (value) => _onPlaceChanged(value),
|
onPlaceChanged: (value) => _onPlaceChanged(value),
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
import 'place.dart';
|
import 'place.dart';
|
||||||
@@ -65,7 +67,7 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
// Draw initial place markers on creation so that we have something
|
// Draw initial place markers on creation so that we have something
|
||||||
// interesting to look at.
|
// interesting to look at.
|
||||||
var markers = <Marker>{};
|
var markers = <Marker>{};
|
||||||
for (var place in AppState.of(context).places) {
|
for (var place in Provider.of<AppState>(context, listen: false).places) {
|
||||||
markers.add(await _createPlaceMarker(context, place));
|
markers.add(await _createPlaceMarker(context, place));
|
||||||
}
|
}
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -75,7 +77,7 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
// Zoom to fit the initially selected category.
|
// Zoom to fit the initially selected category.
|
||||||
await _zoomToFitPlaces(
|
await _zoomToFitPlaces(
|
||||||
_getPlacesForCategory(
|
_getPlacesForCategory(
|
||||||
AppState.of(context).selectedCategory,
|
Provider.of<AppState>(context, listen: false).selectedCategory,
|
||||||
_markedPlaces.values.toList(),
|
_markedPlaces.values.toList(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -91,7 +93,8 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
onTap: () => _pushPlaceDetailsScreen(place),
|
onTap: () => _pushPlaceDetailsScreen(place),
|
||||||
),
|
),
|
||||||
icon: await _getPlaceMarkerIcon(context, place.category),
|
icon: await _getPlaceMarkerIcon(context, place.category),
|
||||||
visible: place.category == AppState.of(context).selectedCategory,
|
visible: place.category ==
|
||||||
|
Provider.of<AppState>(context, listen: false).selectedCategory,
|
||||||
);
|
);
|
||||||
_markedPlaces[marker] = place;
|
_markedPlaces[marker] = place;
|
||||||
return marker;
|
return marker;
|
||||||
@@ -113,7 +116,8 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
|
|
||||||
void _onPlaceChanged(Place value) {
|
void _onPlaceChanged(Place value) {
|
||||||
// Replace the place with the modified version.
|
// Replace the place with the modified version.
|
||||||
final newPlaces = List<Place>.from(AppState.of(context).places);
|
final newPlaces =
|
||||||
|
List<Place>.from(Provider.of<AppState>(context, listen: false).places);
|
||||||
final index = newPlaces.indexWhere((place) => place.id == value.id);
|
final index = newPlaces.indexWhere((place) => place.id == value.id);
|
||||||
newPlaces[index] = value;
|
newPlaces[index] = value;
|
||||||
|
|
||||||
@@ -124,10 +128,11 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
// in the main build method due to a modified AppState.
|
// in the main build method due to a modified AppState.
|
||||||
_configuration = MapConfiguration(
|
_configuration = MapConfiguration(
|
||||||
places: newPlaces,
|
places: newPlaces,
|
||||||
selectedCategory: AppState.of(context).selectedCategory,
|
selectedCategory:
|
||||||
|
Provider.of<AppState>(context, listen: false).selectedCategory,
|
||||||
);
|
);
|
||||||
|
|
||||||
AppState.updateWith(context, places: newPlaces);
|
Provider.of<AppState>(context, listen: false).setPlaces(newPlaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updateExistingPlaceMarker({@required Place place}) {
|
void _updateExistingPlaceMarker({@required Place place}) {
|
||||||
@@ -159,7 +164,7 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _switchSelectedCategory(PlaceCategory category) async {
|
Future<void> _switchSelectedCategory(PlaceCategory category) async {
|
||||||
AppState.updateWith(context, selectedCategory: category);
|
Provider.of<AppState>(context, listen: false).setSelectedCategory(category);
|
||||||
await _showPlacesForSelectedCategory(category);
|
await _showPlacesForSelectedCategory(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,11 +238,12 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
id: Uuid().v1(),
|
id: Uuid().v1(),
|
||||||
latLng: _pendingMarker.position,
|
latLng: _pendingMarker.position,
|
||||||
name: _pendingMarker.infoWindow.title,
|
name: _pendingMarker.infoWindow.title,
|
||||||
category: AppState.of(context).selectedCategory,
|
category:
|
||||||
|
Provider.of<AppState>(context, listen: false).selectedCategory,
|
||||||
);
|
);
|
||||||
|
|
||||||
var placeMarker = await _getPlaceMarkerIcon(
|
var placeMarker = await _getPlaceMarkerIcon(context,
|
||||||
context, AppState.of(context).selectedCategory);
|
Provider.of<AppState>(context, listen: false).selectedCategory);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
final updatedMarker = _pendingMarker.copyWith(
|
final updatedMarker = _pendingMarker.copyWith(
|
||||||
@@ -275,18 +281,20 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Add the new place to the places stored in appState.
|
// Add the new place to the places stored in appState.
|
||||||
final newPlaces = List<Place>.from(AppState.of(context).places)
|
final newPlaces =
|
||||||
..add(newPlace);
|
List<Place>.from(Provider.of<AppState>(context, listen: false).places)
|
||||||
|
..add(newPlace);
|
||||||
|
|
||||||
// Manually update our map configuration here since our map is already
|
// Manually update our map configuration here since our map is already
|
||||||
// updated with the new marker. Otherwise, the map would be reconfigured
|
// updated with the new marker. Otherwise, the map would be reconfigured
|
||||||
// in the main build method due to a modified AppState.
|
// in the main build method due to a modified AppState.
|
||||||
_configuration = MapConfiguration(
|
_configuration = MapConfiguration(
|
||||||
places: newPlaces,
|
places: newPlaces,
|
||||||
selectedCategory: AppState.of(context).selectedCategory,
|
selectedCategory:
|
||||||
|
Provider.of<AppState>(context, listen: false).selectedCategory,
|
||||||
);
|
);
|
||||||
|
|
||||||
AppState.updateWith(context, places: newPlaces);
|
Provider.of<AppState>(context, listen: false).setPlaces(newPlaces);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,8 +317,10 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _maybeUpdateMapConfiguration() async {
|
Future<void> _maybeUpdateMapConfiguration() async {
|
||||||
_configuration ??= MapConfiguration.of(AppState.of(context));
|
_configuration ??=
|
||||||
final newConfiguration = MapConfiguration.of(AppState.of(context));
|
MapConfiguration.of(Provider.of<AppState>(context, listen: false));
|
||||||
|
final newConfiguration =
|
||||||
|
MapConfiguration.of(Provider.of<AppState>(context, listen: false));
|
||||||
|
|
||||||
// Since we manually update [_configuration] when place or selectedCategory
|
// Since we manually update [_configuration] when place or selectedCategory
|
||||||
// changes come from the [place_map], we should only enter this if statement
|
// changes come from the [place_map], we should only enter this if statement
|
||||||
@@ -344,6 +354,7 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
_maybeUpdateMapConfiguration();
|
_maybeUpdateMapConfiguration();
|
||||||
|
var state = Provider.of<AppState>(context);
|
||||||
|
|
||||||
return Builder(builder: (context) {
|
return Builder(builder: (context) {
|
||||||
// We need this additional builder here so that we can pass its context to
|
// We need this additional builder here so that we can pass its context to
|
||||||
@@ -364,7 +375,7 @@ class PlaceMapState extends State<PlaceMap> {
|
|||||||
onCameraMove: (position) => _lastMapPosition = position.target,
|
onCameraMove: (position) => _lastMapPosition = position.target,
|
||||||
),
|
),
|
||||||
_CategoryButtonBar(
|
_CategoryButtonBar(
|
||||||
selectedPlaceCategory: AppState.of(context).selectedCategory,
|
selectedPlaceCategory: state.selectedCategory,
|
||||||
visible: _pendingMarker == null,
|
visible: _pendingMarker == null,
|
||||||
onChanged: _switchSelectedCategory,
|
onChanged: _switchSelectedCategory,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'app_model.dart';
|
|
||||||
import 'place.dart';
|
import 'place.dart';
|
||||||
import 'place_list.dart';
|
import 'place_list.dart';
|
||||||
import 'place_map.dart';
|
import 'place_map.dart';
|
||||||
@@ -12,23 +12,10 @@ enum PlaceTrackerViewType {
|
|||||||
list,
|
list,
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlaceTrackerApp extends StatefulWidget {
|
class PlaceTrackerApp extends StatelessWidget {
|
||||||
@override
|
|
||||||
_PlaceTrackerAppState createState() => _PlaceTrackerAppState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PlaceTrackerAppState extends State<PlaceTrackerApp> {
|
|
||||||
AppState appState = AppState();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
builder: (context, child) {
|
|
||||||
return AppModel<AppState>(
|
|
||||||
initialState: AppState(),
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
home: _PlaceTrackerHomePage(),
|
home: _PlaceTrackerHomePage(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -39,6 +26,7 @@ class _PlaceTrackerHomePage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var state = Provider.of<AppState>(context);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Row(
|
title: Row(
|
||||||
@@ -57,18 +45,16 @@ class _PlaceTrackerHomePage extends StatelessWidget {
|
|||||||
padding: EdgeInsets.fromLTRB(0.0, 0.0, 16.0, 0.0),
|
padding: EdgeInsets.fromLTRB(0.0, 0.0, 16.0, 0.0),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
AppState.of(context).viewType == PlaceTrackerViewType.map
|
state.viewType == PlaceTrackerViewType.map
|
||||||
? Icons.list
|
? Icons.list
|
||||||
: Icons.map,
|
: Icons.map,
|
||||||
size: 32.0,
|
size: 32.0,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
AppState.updateWith(
|
state.setViewType(
|
||||||
context,
|
state.viewType == PlaceTrackerViewType.map
|
||||||
viewType:
|
? PlaceTrackerViewType.list
|
||||||
AppState.of(context).viewType == PlaceTrackerViewType.map
|
: PlaceTrackerViewType.map,
|
||||||
? PlaceTrackerViewType.list
|
|
||||||
: PlaceTrackerViewType.map,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -76,61 +62,41 @@ class _PlaceTrackerHomePage extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: IndexedStack(
|
body: IndexedStack(
|
||||||
index:
|
index: state.viewType == PlaceTrackerViewType.map ? 0 : 1,
|
||||||
AppState.of(context).viewType == PlaceTrackerViewType.map ? 0 : 1,
|
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
PlaceMap(center: const LatLng(45.521563, -122.677433)),
|
PlaceMap(center: const LatLng(45.521563, -122.677433)),
|
||||||
PlaceList(),
|
PlaceList()
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppState {
|
class AppState extends ChangeNotifier {
|
||||||
const AppState({
|
AppState({
|
||||||
this.places = StubData.places,
|
this.places = StubData.places,
|
||||||
this.selectedCategory = PlaceCategory.favorite,
|
this.selectedCategory = PlaceCategory.favorite,
|
||||||
this.viewType = PlaceTrackerViewType.map,
|
this.viewType = PlaceTrackerViewType.map,
|
||||||
}) : assert(places != null),
|
}) : assert(places != null),
|
||||||
assert(selectedCategory != null);
|
assert(selectedCategory != null);
|
||||||
|
|
||||||
final List<Place> places;
|
List<Place> places;
|
||||||
final PlaceCategory selectedCategory;
|
PlaceCategory selectedCategory;
|
||||||
final PlaceTrackerViewType viewType;
|
PlaceTrackerViewType viewType;
|
||||||
|
|
||||||
AppState copyWith({
|
void setViewType(PlaceTrackerViewType viewType) {
|
||||||
List<Place> places,
|
this.viewType = viewType;
|
||||||
PlaceCategory selectedCategory,
|
notifyListeners();
|
||||||
PlaceTrackerViewType viewType,
|
|
||||||
}) {
|
|
||||||
return AppState(
|
|
||||||
places: places ?? this.places,
|
|
||||||
selectedCategory: selectedCategory ?? this.selectedCategory,
|
|
||||||
viewType: viewType ?? this.viewType,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static AppState of(BuildContext context) => AppModel.of<AppState>(context);
|
void setSelectedCategory(PlaceCategory newCategory) {
|
||||||
|
selectedCategory = newCategory;
|
||||||
static void update(BuildContext context, AppState newState) {
|
notifyListeners();
|
||||||
AppModel.update<AppState>(context, newState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void updateWith(
|
void setPlaces(List<Place> newPlaces) {
|
||||||
BuildContext context, {
|
places = newPlaces;
|
||||||
List<Place> places,
|
notifyListeners();
|
||||||
PlaceCategory selectedCategory,
|
|
||||||
PlaceTrackerViewType viewType,
|
|
||||||
}) {
|
|
||||||
update(
|
|
||||||
context,
|
|
||||||
AppState.of(context).copyWith(
|
|
||||||
places: places,
|
|
||||||
selectedCategory: selectedCategory,
|
|
||||||
viewType: viewType,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -116,6 +116,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.8"
|
version: "1.1.8"
|
||||||
|
nested:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: nested
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.4"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -144,6 +151,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
|
provider:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: provider
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.5+1"
|
||||||
quiver:
|
quiver:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ dev_dependencies:
|
|||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
pedantic: ^1.9.0
|
pedantic: ^1.9.0
|
||||||
|
provider: ^4.0.5+1
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
assets:
|
assets:
|
||||||
|
|||||||
Reference in New Issue
Block a user