我是新手Flutter
,我花了一些时间来研究提供程序模式,我是一名 PHP 人,所以我对它的工作原理有基本的了解,尤其是在Laravel
框架方面。
对我来说,提供者应该管理数据、从数据库中检索数据、操作广告保存。
据我了解,颤振中的概念是相同的,但遵循文档非常困难。
我创建了一个调用 REST API 的简单应用程序,现在我想将响应添加到我的提供程序以使用我所有页面和小部件中的数据。
这是我的代码。
splash.dart
向我的用户显示启动画面并调用外部端点的文件,在这里我想获取我的数据并添加到提供程序。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'models/maison.dart';
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
class SplashApp extends StatefulWidget {
final VoidCallback onInitializationComplete;
const SplashApp({
Key key,
@required this.onInitializationComplete,
}) : super(key: key);
@override
_SplashAppState createState() => _SplashAppState();
}
class _SplashAppState extends State<SplashApp> {
@override
void initState() {
super.initState();
_initializeAsyncDependencies();
}
Future<void> _initializeAsyncDependencies() async {
var url = 'https://run.mocky.io/v3/95237af1-b13f-4756-b308-56c9aac93c7e';
// Await the http get response, then decode the json-formatted response.
var response = await http.get(url);
if (response.statusCode == 200) {
var jsonResponse = convert.jsonDecode(response.body);
var data = jsonResponse['data'];
var name = data[0]['name'];
print('Name: $name.');
} else {
print('Request failed with status: ${response.statusCode}.');
}
// >>> initialize async dependencies <<<
// >>> register favorite dependency manager <<<
// >>> reap benefits <<<
Future.delayed(
Duration(milliseconds: 3000),
() => widget.onInitializationComplete(),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Splash Screen',
theme: ThemeData(
accentColor: Colors.black,
),
home: _buildBody(),
);
}
Widget _buildBody() {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Color(0xFFDDCDC8),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 2,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.white,
radius: 80.0,
child: Icon(
Icons.access_time,
color: Colors.black,
size: 80.0,
),
),
Padding(
padding: EdgeInsets.only(
top: 10.0,
),
),
Text(
'Title',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 26.0,
),
),
SizedBox(
height: 16.0,
),
Text(
'Subtitle',
style: TextStyle(
fontSize: 16.0,
),
),
],
),
),
),
Expanded(
flex: 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(),
Padding(
padding: EdgeInsets.only(top: 20.0),
),
Text('Caricamento'),
],
),
),
],
)
],
),
);
}
}
这是我的main.dart
文件,在这里我初始化了我的标签和一些东西。我在那里添加了ChangeNotifyer
因为这里我需要数据,也许不是正确的地方?
import 'package:testapp/localization/app_localization.dart';
import 'package:testapp/pages/home.dart';
import 'package:testapp/pages/maison.dart';
import 'package:testapp/pages/map.dart';
import 'package:testapp/splash.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:testapp/providers/maisons_provider.dart';
void main() {
LicenseRegistry.addLicense(() async* {
final license = await rootBundle.loadString('google_fonts/OFL.txt');
yield LicenseEntryWithLineBreaks(['google_fonts'], license);
});
runApp(
SplashApp(
key: UniqueKey(),
onInitializationComplete: () => runMainApp(),
),
);
}
void runMainApp() {
runApp(
MyApp(),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return ChangeNotifierProvider(
builder: (ctx) => MaisonsProvider(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Title',
theme: ThemeData(
primaryColor: Colors.black,
scaffoldBackgroundColor: Color(0xFFDDCDC8),
visualDensity: VisualDensity.adaptivePlatformDensity,
textTheme: GoogleFonts.montserratTextTheme(textTheme).copyWith(
headline1: GoogleFonts.montserrat(
textStyle: textTheme.headline1,
fontSize: 30,
fontWeight: FontWeight.w600,
color: Colors.black,
),
headline2: GoogleFonts.montserrat(
textStyle: textTheme.headline1,
fontSize: 22,
fontWeight: FontWeight.w500,
color: Colors.black,
),
bodyText1: GoogleFonts.montserrat(
textStyle: textTheme.bodyText1,
color: Colors.black,
fontWeight: FontWeight.w400,
fontSize: 19,
),
),
),
home: BottomBar(),
routes: {
MaisonPage.routeName: (ctx) => MaisonPage(),
},
supportedLocales: [
Locale('en', 'US'),
Locale('it', 'IT'),
],
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
),
);
}
}
class BottomBar extends StatefulWidget {
@override
_BottomBarState createState() => _BottomBarState();
}
class _BottomBarState extends State<BottomBar> {
int _currentIndex = 0;
final List<Widget> _children = [
HomePage(),
MapPage(),
];
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Color(0xFFDDCDC8),
currentIndex: _currentIndex,
onTap: onTabTapped,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.list),
title: Text(
AppLocalizations.of(context).translate('tab_maisons'),
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.map,
),
title: Text(
AppLocalizations.of(context).translate('tab_map'),
),
),
],
),
);
}
}
这是我的 Maison 模型。
import 'package:testapp/models/point.dart';
import 'package:flutter/material.dart';
class Maison {
final String id;
final String name;
final String imageUrl;
final String price;
final Point coordinates;
Maison({
@required this.id,
@required this.name,
@required this.price,
@required this.imageUrl,
@required this.coordinates,
});
}
这是提供者:
import 'package:testapp/models/point.dart';
import 'package:flutter/material.dart';
import '../models/maison.dart';
class MaisonsProvider with ChangeNotifier {
// Questa lista è privata, non può essere recuperata dall'esterno, serve un getter
List<Maison> _items = [
Maison(
id: '1',
name: 'Prova 1',
price: '60€',
imageUrl:
'https://images.unsplash.com/photo-1495562569060-2eec283d3391?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80',
coordinates: Point(
lat: 45.4640976,
lng: 9.1897378,
),
),
Maison(
id: '2',
name: 'Prova 2',
price: 'Free',
imageUrl:
'https://images.unsplash.com/photo-1582559934353-2e47140e7501?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1788&q=80',
coordinates: Point(
lat: 45.4640976,
lng: 10.1897378,
),
),
Maison(
id: '3',
name: 'Prova 3',
price: 'Free',
imageUrl:
'https://images.unsplash.com/photo-1553355617-f7342d67a95f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80',
coordinates: Point(
lat: 45.9,
lng: 10.1897378,
),
),
Maison(
id: '4',
name: 'Prova 4',
price: '40€',
imageUrl:
'https://images.unsplash.com/photo-1555141816-810dd5692b6a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1789&q=80',
coordinates: Point(
lat: 46.4640976,
lng: 9.30,
),
),
];
// Getter
// fa in modo che venga ritornata la lista di Maison,
// non è la lista originale ma una copia.
List<Maison> get items {
return [..._items];
}
// Aggiunge una nuova Maison alla lista.
// è importante passare dal provider così che sia lui a informare gli altri widget
// che c'è stato un cambiamento
void addMaison(Maison maison) {
_items.add(maison);
// Informa tutti i widget che sono interessati che c'è una nuova maison
// in questo modo i widget possono fare una rebuild e mostrare i dati corretti
notifyListeners();
}
}
我添加了一个addMaison
方法,该方法应该负责向我添加一个新的 Maison_item
和一个 getter 来检索它的副本。
我试图以这种方式在 splash.dart 中初始化我的提供程序:
final maisonsData = Provider.of<MaisonsProvider>(context);
Maison m = Maison(
id: '1',
name: 'Prova add',
imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/1/17/Google-flutter-logo.png',
coordinates: {
lat: 23,
lng: 23,
}
);
maisonData.addMaison(m);
我尝试将其添加到我_initializeAsyncDependencies
的应用程序中,但应用程序一直显示启动画面并且无法继续。
如何在 http 请求中使用提供程序?