首页 > 解决方案 > 如何移动函数**FuturefetchData()** 到服务类

问题描述

我想将我的代码重组为MVVM,我是新手,如何将上面的函数重组为Service Class import 'dart:convert';

import 'package:amaizi_test/models/UserModel.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class JsonApiPhp extends StatefulWidget {
  @override
  _JsonApiPhpState createState() => _JsonApiPhpState();
}

class _JsonApiPhpState extends State<JsonApiPhp> {

  bool loading = true;
  final String url = 'https://jsonplaceholder.typicode.com/users';
  var client = http.Client();
  List<UserModel> users = [];


  @override
  void initState(){
    fetchData();
    super.initState();
  }

我想重组我的文件,

  Future<void> fetchData() async {
    http.Response response = await client.get(Uri.parse(url));
    if(response.statusCode == 200){ // Connection Ok
      List responseJson = json.decode(response.body);
      responseJson.map((m) => users.add(new UserModel.fromJson(m))).toList();
      setState(() {
        loading = false;
      });
    } else {
      throw('error');
    }
  }

并在 HomePage InitState 中初始化

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        child: loading ?
        Container(
          child: Center(
            child: CircularProgressIndicator(),
          ),
        ) :
        ListView.builder(
          itemCount: users.length,
          itemBuilder: (BuildContext context, int index){
            return Card(
              child: ListTile(
                title: Text(
                  users[index].name,
                ),
              ),
            );
          },
        )
      ),
    );
  }
}

// 函数调用API并显示在UI中

标签: flutterdart

解决方案


例如,您可以在 lib 目录中创建目录“services”,然后使用您的服务类在该目录中创建 dart 文件。例如:

class ServerApiService{
  Future<List<User>> fetchData() async {
    ///your code, but without setState()
    return users;
  }
}

在 initState 之后,您可以创建服务对象并从服务类调用 fetchData 函数。但不是每次都创建服务类对象,我建议在 MaterialApp 之上创建服务对象,并在应用程序的任何小部件中使用 Provider 访问服务对象。

您可以使用 FutureBuilder 小部件从 fetchData() 方法访问数据。

FutureBuilder<List<User>>(
    future: users,
    builder: (context, snapshot) {
      if (snapshot.hasData) {
        var data = snapshot.data!;
        return ListView.builder(
            itemCount: data.length,
            itemBuilder: (BuildContext context, int index) {
              User user = data[index];
              return Card(
                  child: ListTile(
                  title: Text(
                  user.name,
                 ),
                ),
               )
            });
      }
      else if (snapshot.hasError) {
        return Text("${snapshot.error}");
      }
      else {
        return Container(
          child: Center(
            child: CircularProgressIndicator(),
          ),
        );
      }
    });

访问 FutureBuilder(未来:用户)的用户从服务对象获取数据。

还有一点注意:如果在 initState() 内部,您将在其他代码上方调用 super.initState() 会更好。用 super.initState 开始你的 initState,用 super.dispose 结束你的 dispose


推荐阅读