【问题标题】:how to fetch data from Api using statelessWidget如何使用 statelessWidget 从 Api 获取数据
【发布时间】:2024-01-24 08:02:01
【问题描述】:

我正在尝试从 api 获取新闻数据并在主页中显示新闻标题 我知道它不会有任何内部更改,所以我决定使用 StatelessWidget 以及使用 PROVIDER 状态管理 现在我遇到了如何使用 StatelessWidget 调用 fetching 方法以便显示标题的问题

这是我的获取数据类

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() 方法来运行所有人员

【问题讨论】:

    标签: flutter dart state-management


    【解决方案1】:

    你可以直接在你的ChangeNotifier的构造函数中发起请求:

    class MyNotifier with ChangeNotifer {
      MyNotifier() {
        // TODO: do an http request
      }
    }
    

    【讨论】:

    • 那异步 .. 等待 ??修饰符“异步”不能应用于构造函数的主体。尝试删除修饰符
    • 只要在里面打电话给你的fetchData
    【解决方案2】:

    你应该用 Consumer 包裹你的身体, 类似的东西:

    Consumer(BuildContext context , NewsRequest model , child) 
    {
     return model.isFetching? 
     // put the rest of your code here 
    }
    

    【讨论】:

      【解决方案3】:

      所以,选项是:

      1. 加载屏幕。获取数据。更新画面。
      2. 在屏幕加载之前获取数据。使用预取的数据加载屏幕。

      您可能知道,第一个是有状态的,而选项 #2 是无状态的。

      AFAIK,最好的方法是:

      1. 在无状态类中创建一个属性,该属性保存要在屏幕上显示的数据。 (因此,您的案例中的新闻信息)。
      2. 在启动画面/主屏幕加载期间获取数据。并通过将数据传递给屏幕来调用屏幕。

      示例实现: 在我的一个应用程序中,我有一个要从 Web API 获取并显示在移动应用程序中的列表。我将整体功能分为两个文件。列表一的主文件/类是无状态的。

      在头文件中,我得到如下数据:

      @override
        void didChangeDependencies() {
          super.didChangeDependencies();
            _requestLeaveList();
          }
      

      这会设置一个名为 _leaveList 的变量。

      现在,我将屏幕调用如下:

      Expanded(
         child: LeaveListView(leaves: _listLeaves,),
      )
      

      LeaveListView 是无状态的。

      【讨论】: