如何使用 statelessWidget 从 Api 获取数据
how to fetch data from Api using statelessWidget
我正在尝试从 api 获取新闻数据并在主页中显示新闻标题
据我所知,它不会有任何内部更改,所以我决定使用 StatelessWidget 以及使用 PROVIDER 状态管理
现在我遇到了如何使用 StatelessWidget 调用获取方法以便显示标题的问题
这是我的抓取数据class
class NewsRequest with ChangeNotifier{
static String _url ="https://newsapi.org/v2/everything?q=bitcoin&from=2019-06-24&sortBy=publishedAt&apiKey=4d990bdd71324572bca39fe31edc3990";
static Map<String, String> _apiKey = {"apiKey" : "4d990bdd71324572bca39fe31edc3990"};
Map <String, dynamic> _data;
List _articles;
bool _isFetching = false;
Map<String, dynamic> result;
bool get isFetching => _isFetching;
Future<Map<String, dynamic>> fetchData() async{
_isFetching = true;
try{
Response response = await get(Uri.encodeFull(_url), headers: _apiKey)
.timeout(Duration(seconds: 60));
print("STATUSCODE ${response.statusCode}");
if(response.statusCode == 200){
_data = json.decode(response.body);
}
_isFetching = false;
notifyListeners();
}on SocketException catch(_){
}on TimeoutException catch(_){
}catch(e){
e.toString();
print('CATCH ${e.toString()}');
}
return null;
}
Map<String, dynamic> get getNews => _data;
Map<String , dynamic> getNewsData(){
if(_data == null){
print('data is null');
return null;
}else{
_articles = _data['articles'];
}
print("FIRST ARTICALE IS : ${_articles[0]}");
return null;
}
}
我的主页调用是
body: newsResponse.isFetching
? Center(
child: CircularProgressIndicator(),
)
: newsResponse.getNewsData()!= null ?
new ListView.builder(
itemCount: newsResponse.getNewsData().length,
itemBuilder: (BuildContext context, int index) {
return new Container(
padding: EdgeInsets.all(10),
child: Stack(
children: <Widget>[
Container(
height: 100,
width: 310,
),
child: Wrap(children: <Widget>[
Text( newsResponse.result['response'][index]['title']),
]),
),
CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(
newsResponse.result['response'][index]["urlToImage"]??"",
),
),
],
),
);
},
):
Container()
我需要调用 fetchData() 方法以便 运行 所有员工
您可以直接在 ChangeNotifier
:
的构造函数中启动请求
class MyNotifier with ChangeNotifer {
MyNotifier() {
// TODO: do an http request
}
}
你应该用 Consumer 包装你的 body ,类似这样的东西:
Consumer(BuildContext context , NewsRequest model , child)
{
return model.isFetching?
// put the rest of your code here
}
所以,选项是:
- 加载屏幕。获取数据。更新画面。
- 在屏幕加载之前获取数据。使用预取数据加载屏幕。
如您所知,第一个是有状态的,而选项 #2 是无状态的。
据我所知,最好的方法是:
- 在 Stateless 的 class 中创建一个 属性 来保存要在屏幕上显示的数据。 (因此,您的案例中的新闻信息)。
- 在 splash/main 屏幕加载期间获取数据。并通过将数据传递给它来调用屏幕。
示例实现:
在我的一个应用程序中,我有一个列表可以从网络 API 中获取并显示在移动应用程序中。我将整体功能分为两个文件。列表中的主要 file/class 是无状态的。
在头文件中,我得到如下数据:
@override
void didChangeDependencies() {
super.didChangeDependencies();
_requestLeaveList();
}
这会设置一个名为 _leaveList 的变量。
现在,我调用屏幕如下:
Expanded(
child: LeaveListView(leaves: _listLeaves,),
)
并且 LeaveListView 是无状态的。
我正在尝试从 api 获取新闻数据并在主页中显示新闻标题 据我所知,它不会有任何内部更改,所以我决定使用 StatelessWidget 以及使用 PROVIDER 状态管理 现在我遇到了如何使用 StatelessWidget 调用获取方法以便显示标题的问题
这是我的抓取数据class
class NewsRequest with ChangeNotifier{
static String _url ="https://newsapi.org/v2/everything?q=bitcoin&from=2019-06-24&sortBy=publishedAt&apiKey=4d990bdd71324572bca39fe31edc3990";
static Map<String, String> _apiKey = {"apiKey" : "4d990bdd71324572bca39fe31edc3990"};
Map <String, dynamic> _data;
List _articles;
bool _isFetching = false;
Map<String, dynamic> result;
bool get isFetching => _isFetching;
Future<Map<String, dynamic>> fetchData() async{
_isFetching = true;
try{
Response response = await get(Uri.encodeFull(_url), headers: _apiKey)
.timeout(Duration(seconds: 60));
print("STATUSCODE ${response.statusCode}");
if(response.statusCode == 200){
_data = json.decode(response.body);
}
_isFetching = false;
notifyListeners();
}on SocketException catch(_){
}on TimeoutException catch(_){
}catch(e){
e.toString();
print('CATCH ${e.toString()}');
}
return null;
}
Map<String, dynamic> get getNews => _data;
Map<String , dynamic> getNewsData(){
if(_data == null){
print('data is null');
return null;
}else{
_articles = _data['articles'];
}
print("FIRST ARTICALE IS : ${_articles[0]}");
return null;
}
}
我的主页调用是
body: newsResponse.isFetching
? Center(
child: CircularProgressIndicator(),
)
: newsResponse.getNewsData()!= null ?
new ListView.builder(
itemCount: newsResponse.getNewsData().length,
itemBuilder: (BuildContext context, int index) {
return new Container(
padding: EdgeInsets.all(10),
child: Stack(
children: <Widget>[
Container(
height: 100,
width: 310,
),
child: Wrap(children: <Widget>[
Text( newsResponse.result['response'][index]['title']),
]),
),
CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(
newsResponse.result['response'][index]["urlToImage"]??"",
),
),
],
),
);
},
):
Container()
我需要调用 fetchData() 方法以便 运行 所有员工
您可以直接在 ChangeNotifier
:
class MyNotifier with ChangeNotifer {
MyNotifier() {
// TODO: do an http request
}
}
你应该用 Consumer 包装你的 body ,类似这样的东西:
Consumer(BuildContext context , NewsRequest model , child)
{
return model.isFetching?
// put the rest of your code here
}
所以,选项是:
- 加载屏幕。获取数据。更新画面。
- 在屏幕加载之前获取数据。使用预取数据加载屏幕。
如您所知,第一个是有状态的,而选项 #2 是无状态的。
据我所知,最好的方法是:
- 在 Stateless 的 class 中创建一个 属性 来保存要在屏幕上显示的数据。 (因此,您的案例中的新闻信息)。
- 在 splash/main 屏幕加载期间获取数据。并通过将数据传递给它来调用屏幕。
示例实现: 在我的一个应用程序中,我有一个列表可以从网络 API 中获取并显示在移动应用程序中。我将整体功能分为两个文件。列表中的主要 file/class 是无状态的。
在头文件中,我得到如下数据:
@override
void didChangeDependencies() {
super.didChangeDependencies();
_requestLeaveList();
}
这会设置一个名为 _leaveList 的变量。
现在,我调用屏幕如下:
Expanded(
child: LeaveListView(leaves: _listLeaves,),
)
并且 LeaveListView 是无状态的。