0

我正在使用flutter http包处理flutter中的网络请求。

到目前为止,我有一个欢迎屏幕和一个网络助手。

欢迎屏幕有一个带有列表视图和底部栏的脚手架。

列表视图将显示每个列表项的文本和图像。

这些项目的数据来自 HTTP 请求。

该请求是在我的网络助手类中完成的。

在欢迎屏幕中,我有一个从 initState() 调用的函数,该函数将为从网络帮助程序返回的 json 设置一个局部变量,但是一旦我尝试从该变量访问数据,它就为空。但是,如果我只是打印数据,那么数据就在那里。

我的问题是我已经访问了数据,但想不出如何将数据传递到列表视图中。

这是我的网络助手类代码的样子

import 'package:http/http.dart' as http;
import 'dart:convert';

class NetworkHelper{
  //Sets up search filter variables
  int year;
  String make;
  String model;
  String condition;
  String combustible;
  String style;
  String color;
  double minPrice;
  double maxPrice;

  Future fetchAlbum() async {
    http.Response response = await http.get('https://jsonplaceholder.typicode.com/todos');

    if (response.statusCode == 200) {
      String data = response.body;
      return jsonDecode(data);
    } else {
      throw Exception('Failed to load album');
    }
  }


}

这是我的欢迎屏幕的样子

import 'package:flutter/material.dart';
import 'package:components/appBarTitle.dart';
import 'package:components/bottomBarComponent.dart';
import 'package:convex_bottom_bar/convex_bottom_bar.dart';
import 'package:constants.dart';
import 'package:helpers/network_helper.dart';
import 'dart:convert';

class WelcomeScreen extends StatefulWidget {
  static String id = '/welcome_screen';
  @override
  _WelcomeScreenState createState() => _WelcomeScreenState();
}

class _WelcomeScreenState extends State<WelcomeScreen> {

  int _index = 0;

  NetworkHelper http = NetworkHelper();
  dynamic data;
  Future testMethod () async {
    this.data = await http.fetchAlbum();
    print(this.data);
  }

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

  @override
  Widget build(BuildContext context) {


    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        elevation: 0.0,
        title: AppBarTitle(),
      ),
      body: Padding(
        padding: const EdgeInsets.all(12.0),
        child: ListView(
          children: [
            ListBody(
              children: [
                Card(
                  child: Row(
                    children: [
                      Expanded(
                        child: Column(
                          children: [
                            Text('2017 Nissan', style: TextStyle(fontWeight: FontWeight.w300,)),
                            Text('Versa 1.6 SL', style: TextStyle(fontWeight: FontWeight.w100,)),
                            Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: Text('\$7,998.00', style: TextStyle(fontWeight: FontWeight.w200,)),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        child: Image.network('https://via.placeholder.com/450/0000FF', scale: 4,),

                      ),

                    ],
                  ),
                ),
                Card(
                  child: Row(
                    children: [
                      Expanded(
                        child: Column(
                          children: [
                            Text('2017 Nissan', style: TextStyle(fontWeight: FontWeight.w300,)),
                            Text('Versa 1.6 SL', style: TextStyle(fontWeight: FontWeight.w100,)),
                            Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: Text('\$7,998.00', style: TextStyle(fontWeight: FontWeight.w200,)),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        child: Image.network('https://via.placeholder.com/450/0000FF', scale: 4,),

                      ),

                    ],
                  ),
                ),
                Card(
                  child: Row(
                    children: [
                      Expanded(
                        child: Column(
                          children: [
                            Text('2017 Nissan', style: TextStyle(fontWeight: FontWeight.w300,)),
                            Text('Versa 1.6 SL', style: TextStyle(fontWeight: FontWeight.w100,)),
                            Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: Text('\$7,998.00', style: TextStyle(fontWeight: FontWeight.w200,)),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        child: Image.network('https://via.placeholder.com/450/0000FF', scale: 4,),

                      ),

                    ],
                  ),
                ),
                Card(
                  child: Row(
                    children: [
                      Expanded(
                        child: Column(
                          children: [
                            Text('2017 Nissan', style: TextStyle(fontWeight: FontWeight.w300,)),
                            Text('Versa 1.6 SL', style: TextStyle(fontWeight: FontWeight.w100,)),
                            Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: Text('\$7,998.00', style: TextStyle(fontWeight: FontWeight.w200,)),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        child: Image.network('https://via.placeholder.com/450/0000FF', scale: 4,),

                      ),

                    ],
                  ),
                ),
                Card(
                  child: Row(
                    children: [
                      Expanded(
                        child: Column(
                          children: [
                            Text('2017 Nissan', style: TextStyle(fontWeight: FontWeight.w300,)),
                            Text('Versa 1.6 SL', style: TextStyle(fontWeight: FontWeight.w100,)),
                            Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: Text('\$7,998.00', style: TextStyle(fontWeight: FontWeight.w200,)),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        child: Image.network('https://via.placeholder.com/450/0000FF', scale: 4,),

                      ),

                    ],
                  ),
                ),
                Card(
                  child: Row(
                    children: [
                      Expanded(
                        child: Column(
                          children: [
                            Text('2017 Nissan', style: TextStyle(fontWeight: FontWeight.w300,)),
                            Text('Versa 1.6 SL', style: TextStyle(fontWeight: FontWeight.w100,)),
                            Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: Text('\$7,998.00', style: TextStyle(fontWeight: FontWeight.w200,)),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        child: Image.network('https://via.placeholder.com/450/0000FF', scale: 4,),

                      ),

                    ],
                  ),
                )
              ],
            ),

          ],
        ),
      ),
        bottomNavigationBar: ConvexAppBar(
          backgroundColor: Color(0xffe74c3c),
          items: [
            TabItem(icon: Icons.home, title: 'Home'),
            TabItem(icon: Icons.map, title: 'Discover'),
            TabItem(icon: Icons.search, title: 'Busca'),
            TabItem(icon: Icons.person, title: 'Mi Cuenta'),
            TabItem(icon: Icons.build, title: 'Settings'),
          ],
          initialActiveIndex: 2,//optional, default as 0
          onTap: (int i) => print('click index=$i'),
        )
    );
  }
}
4

2 回答 2

1

您可以在下面复制粘贴运行完整代码
您可以使用FutureBuilder并且您可以在 代码片段ListView.builder
下面看到工作演示

Future<List<Payload>> _future;
NetworkHelper http = NetworkHelper();
Future<List<Payload>> testMethod() async {
    var data = await http.fetchAlbum();
    return data;
}

@override
void initState() {
    super.initState();
    _future = testMethod();
}
...  
FutureBuilder(
          future: _future,
          builder: (context, AsyncSnapshot<List<Payload>> snapshot) {
            ...
                } else {
                  return ListView.builder(
                      shrinkWrap: true,
                      itemCount: snapshot.data.length,
                      itemBuilder: (context, index) {
                        return Card(
                          elevation: 6.0,
                          child: Padding(
                            padding: const EdgeInsets.only(
                                top: 6.0,
                                bottom: 6.0,
                                left: 8.0,
                                right: 8.0),
                            child: ListTile(
                              title: Text(
                                  snapshot.data[index].id.toString()),
                              subtitle: Text(
                                snapshot.data[index].title,
                              ),

工作演示

在此处输入图像描述

完整代码

import 'package:convex_bottom_bar/convex_bottom_bar.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
// To parse this JSON data, do
//
//     final payload = payloadFromJson(jsonString);

import 'dart:convert';

List<Payload> payloadFromJson(String str) =>
    List<Payload>.from(json.decode(str).map((x) => Payload.fromJson(x)));

String payloadToJson(List<Payload> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Payload {
  Payload({
    this.userId,
    this.id,
    this.title,
    this.completed,
  });

  int userId;
  int id;
  String title;
  bool completed;

  factory Payload.fromJson(Map<String, dynamic> json) => Payload(
        userId: json["userId"],
        id: json["id"],
        title: json["title"],
        completed: json["completed"],
      );

  Map<String, dynamic> toJson() => {
        "userId": userId,
        "id": id,
        "title": title,
        "completed": completed,
      };
}

class NetworkHelper {
  //Sets up search filter variables
  int year;
  String make;
  String model;
  String condition;
  String combustible;
  String style;
  String color;
  double minPrice;
  double maxPrice;

  Future<List<Payload>> fetchAlbum() async {
    http.Response response =
        await http.get('https://jsonplaceholder.typicode.com/todos');

    if (response.statusCode == 200) {
      //String data = response.body;
      return payloadFromJson(response.body);
    } else {
      throw Exception('Failed to load album');
    }
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: WelcomeScreen(),
    );
  }
}

class WelcomeScreen extends StatefulWidget {
  static String id = '/welcome_screen';
  @override
  _WelcomeScreenState createState() => _WelcomeScreenState();
}

class _WelcomeScreenState extends State<WelcomeScreen> {
  int _index = 0;
  Future<List<Payload>> _future;

  NetworkHelper http = NetworkHelper();

  Future<List<Payload>> testMethod() async {
    var data = await http.fetchAlbum();
    return data;
  }

  @override
  void initState() {
    super.initState();
    _future = testMethod();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.white,
        appBar: AppBar(
          elevation: 0.0,
          title: Text("title"),
        ),
        body: Column(
          children: [
            Expanded(
              flex: 1,
              child: FutureBuilder(
                  future: _future,
                  builder: (context, AsyncSnapshot<List<Payload>> snapshot) {
                    switch (snapshot.connectionState) {
                      case ConnectionState.none:
                        return Text('none');
                      case ConnectionState.waiting:
                        return Center(child: CircularProgressIndicator());
                      case ConnectionState.active:
                        return Text('');
                      case ConnectionState.done:
                        if (snapshot.hasError) {
                          return Text(
                            '${snapshot.error}',
                            style: TextStyle(color: Colors.red),
                          );
                        } else {
                          return ListView.builder(
                              shrinkWrap: true,
                              itemCount: snapshot.data.length,
                              itemBuilder: (context, index) {
                                return Card(
                                  elevation: 6.0,
                                  child: Padding(
                                    padding: const EdgeInsets.only(
                                        top: 6.0,
                                        bottom: 6.0,
                                        left: 8.0,
                                        right: 8.0),
                                    child: ListTile(
                                      title: Text(
                                          snapshot.data[index].id.toString()),
                                      subtitle: Text(
                                        snapshot.data[index].title,
                                      ),
                                    ),
                                  ),
                                );
                              });
                        }
                    }
                  }),
            ),
            Expanded(
              flex: 1,
              child: Padding(
                padding: const EdgeInsets.all(12.0),
                child: ListView(
                  shrinkWrap: true,
                  children: [
                    ListBody(
                      children: [
                        Card(
                          child: Row(
                            children: [
                              Expanded(
                                child: Column(
                                  children: [
                                    Text('2017 Nissan',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w300,
                                        )),
                                    Text('Versa 1.6 SL',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w100,
                                        )),
                                    Padding(
                                      padding: const EdgeInsets.all(8.0),
                                      child: Text('\$7,998.00',
                                          style: TextStyle(
                                            fontWeight: FontWeight.w200,
                                          )),
                                    ),
                                  ],
                                ),
                              ),
                              Expanded(
                                child: Image.network(
                                  'https://via.placeholder.com/450/0000FF',
                                  scale: 4,
                                ),
                              ),
                            ],
                          ),
                        ),
                        Card(
                          child: Row(
                            children: [
                              Expanded(
                                child: Column(
                                  children: [
                                    Text('2017 Nissan',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w300,
                                        )),
                                    Text('Versa 1.6 SL',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w100,
                                        )),
                                    Padding(
                                      padding: const EdgeInsets.all(8.0),
                                      child: Text('\$7,998.00',
                                          style: TextStyle(
                                            fontWeight: FontWeight.w200,
                                          )),
                                    ),
                                  ],
                                ),
                              ),
                              Expanded(
                                child: Image.network(
                                  'https://via.placeholder.com/450/0000FF',
                                  scale: 4,
                                ),
                              ),
                            ],
                          ),
                        ),
                        Card(
                          child: Row(
                            children: [
                              Expanded(
                                child: Column(
                                  children: [
                                    Text('2017 Nissan',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w300,
                                        )),
                                    Text('Versa 1.6 SL',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w100,
                                        )),
                                    Padding(
                                      padding: const EdgeInsets.all(8.0),
                                      child: Text('\$7,998.00',
                                          style: TextStyle(
                                            fontWeight: FontWeight.w200,
                                          )),
                                    ),
                                  ],
                                ),
                              ),
                              Expanded(
                                child: Image.network(
                                  'https://via.placeholder.com/450/0000FF',
                                  scale: 4,
                                ),
                              ),
                            ],
                          ),
                        ),
                        Card(
                          child: Row(
                            children: [
                              Expanded(
                                child: Column(
                                  children: [
                                    Text('2017 Nissan',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w300,
                                        )),
                                    Text('Versa 1.6 SL',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w100,
                                        )),
                                    Padding(
                                      padding: const EdgeInsets.all(8.0),
                                      child: Text('\$7,998.00',
                                          style: TextStyle(
                                            fontWeight: FontWeight.w200,
                                          )),
                                    ),
                                  ],
                                ),
                              ),
                              Expanded(
                                child: Image.network(
                                  'https://via.placeholder.com/450/0000FF',
                                  scale: 4,
                                ),
                              ),
                            ],
                          ),
                        ),
                        Card(
                          child: Row(
                            children: [
                              Expanded(
                                child: Column(
                                  children: [
                                    Text('2017 Nissan',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w300,
                                        )),
                                    Text('Versa 1.6 SL',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w100,
                                        )),
                                    Padding(
                                      padding: const EdgeInsets.all(8.0),
                                      child: Text('\$7,998.00',
                                          style: TextStyle(
                                            fontWeight: FontWeight.w200,
                                          )),
                                    ),
                                  ],
                                ),
                              ),
                              Expanded(
                                child: Image.network(
                                  'https://via.placeholder.com/450/0000FF',
                                  scale: 4,
                                ),
                              ),
                            ],
                          ),
                        ),
                        Card(
                          child: Row(
                            children: [
                              Expanded(
                                child: Column(
                                  children: [
                                    Text('2017 Nissan',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w300,
                                        )),
                                    Text('Versa 1.6 SL',
                                        style: TextStyle(
                                          fontWeight: FontWeight.w100,
                                        )),
                                    Padding(
                                      padding: const EdgeInsets.all(8.0),
                                      child: Text('\$7,998.00',
                                          style: TextStyle(
                                            fontWeight: FontWeight.w200,
                                          )),
                                    ),
                                  ],
                                ),
                              ),
                              Expanded(
                                child: Image.network(
                                  'https://via.placeholder.com/450/0000FF',
                                  scale: 4,
                                ),
                              ),
                            ],
                          ),
                        )
                      ],
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
        bottomNavigationBar: ConvexAppBar(
          backgroundColor: Color(0xffe74c3c),
          items: [
            TabItem(icon: Icons.home, title: 'Home'),
            TabItem(icon: Icons.map, title: 'Discover'),
            TabItem(icon: Icons.search, title: 'Busca'),
            TabItem(icon: Icons.person, title: 'Mi Cuenta'),
            TabItem(icon: Icons.build, title: 'Settings'),
          ],
          initialActiveIndex: 2, //optional, default as 0
          onTap: (int i) => print('click index=$i'),
        ));
  }
}
于 2020-10-30T05:57:04.633 回答
1

最佳实践是添加一些抽象层。不要在一个地方做这一切。

为每条传入数据创建一个数据模型。然后将这些对象的列表传递给列表视图。

此示例设置调用并创建对象:

Future<List<HowTo>> fetchHowTos() async {
    // get the full web resource path based on environment, etc.
    String callPath = webAPI.getHowToPath();
    // just make the call, don't parse yet
    dynamic response = await makeCall(path: callPath);
    try {
      // this is the object type we want to convert the data into so it's easier to work with throughout your app
      List<HowTo> howTos = [];
      if (response != null) {
        // decode the data and then send each piece into a fromJson method
        dynamic howTosJson = json.decode(response.body);
        howTosJson.forEach((howToJson) {
          howTos.add(HowTo.fromJson(howToJson));
        });
      }
      return howTos;
    } catch (error, stacktrace) {
      logger.error(error, stacktrace, context: 'error parsing how to content');
      return [];
    }
  }

这段代码实际上进行了调用:

Future<dynamic> makeCall({String path}) async {
    try {
      final response = await network.getCall(path: path);

      if (response.statusCode == 200) {
        // If server returns an OK response, parse the JSON.
        return response;
      } else if (response.statusCode == 404) {
        // if no document exists return null.  expected for items without recommendations
        return null;
      } else {
        throw Exception('Failed http call. status: ' +
            response.statusCode.toString());
      }
    } catch (error, stacktrace) {
      logger.error(error, stacktrace, context: 'path: $path');
    }
}

这是要在您的应用程序中创建和使用的对象

class HowTo {
  final String id;
  final String title;
  final int order;

  HowTo({
    this.id,
    this.title,
    this.order,
  });

  factory HowTo.from(HowTo howTo) {
    return HowTo(
      id: howTo.id,
      title: howTo.title,
      order: howTo.order,
    );
  }

  factory HowTo.fromJson(Map<String, dynamic> json) {
    
    return HowTo(
      id: json['id'] ?? '',
      title: json['Title'] ?? '',
      order: json['Order'] ?? 0,
    );
  }
}

将此响应传递给您的列表视图包装器

List<HowTo> howTos = await fetchHowTos();
于 2020-10-29T23:58:04.700 回答