如果我使用提供程序,如何在App启动时调用方法? [英] How to call method at App start if I am using provider?
问题描述
我想完成对服务器的get
请求,以便在启动时获取我的应用程序的数据.我阅读了一些主题,这些主题描述了在构建窗口小部件后如何运行方法.但是所有这些都是在不使用provider
时的描述情况.而且我不确定在小部件内执行此请求是否是个好主意.
I want to complete get
request to server to get data for my app at it start. I read several topics that describe how to run method after building widgets. But all of them are describe situations when provider
is not using. And I am not sure that it's good idea to do this request inside widget.
我尝试了几种方法,但没有成功. 这是我的代码:
I tried several approaches but did not get success. Here is my code:
void main() async {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ChangeNotifierProvider<TenderApiData>(
builder: (_) => TenderApiData(), child: HomePage()),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(), body: MainContainer());
}
}
class TenderApiData with ChangeNotifier {
String access_token;
List<Map<String, String>> id_names;
String access_token_url = "https://...";
getApiKey() async { // I need to call this method at app start up
var response = await http
.post(access_token_url, headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
access_token = json.decode(response.body)['access_token'];
notifyListeners();
}
}
}
class MyTestWidget extends StatefulWidget {
MyTestWidgetState createState() => MyTestWidgetState();
}
class MyTestWidgetState extends State<MyTestWidget> {
bool isKeyGetted = false;
// before I used this when I extracted data on click event.
// I am not sure that it's needed now
@override
void didChangeDependencies() {
if (!isKeyGetted) {
Provider.of<TenderApiData>(context).getApiKey();
isKeyGetted = !isKeyGetted;
}
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
if (!isKeyGetted) {
Provider.of<TenderApiData>(context).getApiKey();
isKeyGetted = !isKeyGetted;
}
var result = Provider.of<TenderApiData>(context).access_token;
var test = Provider.of<TenderApiData>(context).id_names;
return Column(
children: <Widget>[
RaisedButton(
onPressed: Provider.of<TenderApiData>(context).getRegionsList,
child: Text("get regions"),
),
],
);
}
}
class MainContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Table(
children: [
TableRow(children: [
Row(
children: <Widget>[
Container(child: MyTestWidget()),
Container(child: Text("Regions"),),
Expanded(child: SelectRegions(), )
],
)
]),
TableRow(children: [
Row(
children: <Widget>[
Text("Label"),
Text("Value"),
],
)
]),
],
);
}
}
推荐答案
您可以将TenderApiData
存储为MyApp
的成员,在MyApp
构造函数中进行启动调用,然后将现有实例传递给后代.
这是它的外观:
You can store TenderApiData
as member of MyApp
, make a startup call in MyApp
constructor and pass existing instance to descendants.
Here is how it will look:
class MyApp extends StatelessWidget {
final TenderApiData _tenderApiData = TenderApiData();
MyApp() {
_tenderApiData.getApiKey();
};
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ChangeNotifierProvider<TenderApiData>(
builder: (_) => _tenderApiData, child: HomePage()),
);
}
}
其他类别将保持不变.
另一种选择是将TenderApiData
作为构造函数参数传递到MyApp
中,使其更具可测试性.
Another option would be to pass TenderApiData
as constructor parameter into MyApp
, making it more testable.
void main() {
final TenderApiData tenderApiData = TenderApiData();
tenderApiData.getApiKey(); // call it here or in MyApp constructor - now it can be mocked and tested
runApp(MyApp(tenderApiData));
}
class MyApp extends StatelessWidget {
final TenderApiData _tenderApiData;
MyApp(this._tenderApiData);
// ...
这篇关于如果我使用提供程序,如何在App启动时调用方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!