如何在下拉菜单中显示来自API的数据

发布于 2025-02-10 15:29:45 字数 211 浏览 3 评论 0原文

我需要在下拉列表中显示来自API获取请求的数据,从下拉菜单中选择项目时,我需要将所选项目的ID保存到变量中。

这是URL“ https://reqres.in/api/users?page=1”。

我已经检查了其他帖子,但似乎语法发生了很大变化。

我是新来的扑朔迷离。

从上面的URL中,我需要将“数据”阵列保存到列表中。

I need to display data from an API get request in a dropdown, and when selecting a item from the drop down menu I need to save the id of the selected item into a variable.

Here is the URL "https://reqres.in/api/users?page=1".

I have checked other posts already, but seems like the syntax changed a lot.

I am new to flutter.

From the above URL, I need the "data" array saved into a list.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

Oo萌小芽oO 2025-02-17 15:29:45

您可以使用 futornbuilder 下拉准备就绪了。

下面的代码将解决问题。还要查看 dartpad 的实时演示。

屏幕截图

组件无选的下拉菜单用户选择
dropdownbutton“下拉菜单”
>a href =“ https://i.sstatic.net/yjvk1.png” rel =“ nofollow noreferrer”> -“
import 'dart:convert';

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class User {
  final int id;
  final String email;
  final String firstName;
  final String lastName;
  final String avatar;

  const User({
    required this.id,
    required this.email,
    required this.firstName,
    required this.lastName,
    required this.avatar,
  });

  User.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        email = json['email'],
        firstName = json['first_name'],
        lastName = json['last_name'],
        avatar = json['avatar'];
}

class UsersResponse {
  final int page;
  final int perPage;
  final int total;
  final int totalPages;
  final List<User> data;

  const UsersResponse({
    required this.page,
    required this.perPage,
    required this.total,
    required this.totalPages,
    required this.data,
  });

  UsersResponse.fromJson(Map<String, dynamic> json)
      : page = json['page'],
        perPage = json['per_page'],
        total = json['total'],
        totalPages = json['total_pages'],
        data = (json['data'] as List<dynamic>)
            .map((json) => User.fromJson(json))
            .toList();
}

class _MyHomePageState extends State<MyHomePage> {
  late Future<List<User>> _future;
  User? _selectedUser;
  var _currentIndex = 0;

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

  Future<List<User>> _getUsers() async {
    final response =
        await http.get(Uri.parse('https://reqres.in/api/users?page=1'));
    Map<String, dynamic> json = jsonDecode(response.body);
    final usersResponse = UsersResponse.fromJson(json);
    return usersResponse.data;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.list), label: 'Dropdown'),
          BottomNavigationBarItem(icon: Icon(Icons.list), label: 'ListView'),
        ],
        currentIndex: _currentIndex,
        onTap: (index) => setState(() => _currentIndex = index),
      ),
      body: Center(
        child: FutureBuilder<List<User>>(
            future: _future,
            builder: (context, snapshot) {
              if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              }

              if (snapshot.data == null) {
                return const CircularProgressIndicator();
              }

              return Padding(
                padding: const EdgeInsets.all(12.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: <Widget>[
                    const Text(
                      'Select user:',
                    ),
                    if (_currentIndex == 0)
                      SizedBox(
                        height: 64,
                        child: DropdownButton<User>(
                          onChanged: (user) =>
                              setState(() => _selectedUser = user),
                          value: _selectedUser,
                          items: [
                            ...snapshot.data!.map(
                              (user) => DropdownMenuItem(
                                value: user,
                                child: Row(
                                  children: [
                                    Image.network(user.avatar),
                                    Text('${user.firstName} ${user.lastName}'),
                                  ],
                                ),
                              ),
                            )
                          ],
                        ),
                      ),
                    if (_currentIndex == 1)
                      Expanded(
                        child: ListView.separated(
                          itemBuilder: (context, index) => ElevatedButton(
                            onPressed: () => setState(
                                () => _selectedUser = snapshot.data![index]),
                            style: identical(
                                    _selectedUser, snapshot.data![index])
                                ? ButtonStyle(
                                    backgroundColor: MaterialStateProperty.all(
                                        Colors.blue[400]),
                                    overlayColor: MaterialStateProperty.all(
                                        Colors.black12),
                                  )
                                : ButtonStyle(
                                    backgroundColor:
                                        MaterialStateProperty.all(Colors.white),
                                    overlayColor: MaterialStateProperty.all(
                                        Colors.black12),
                                  ),
                            child: Padding(
                              padding: const EdgeInsets.all(4.0),
                              child: Row(
                                children: [
                                  SizedBox(
                                      height: 64,
                                      child: Image.network(
                                          snapshot.data![index].avatar)),
                                  Text(
                                    '${snapshot.data![index].firstName} ${snapshot.data![index].lastName}',
                                    style: const TextStyle(color: Colors.black),
                                  ),
                                ],
                              ),
                            ),
                          ),
                          separatorBuilder: (context, _) =>
                              const SizedBox(height: 12),
                          itemCount: snapshot.data!.length,
                        ),
                      ),
                  ],
                ),
              );
            }),
      ),
    );
  }
}

JSON响应来自 https:// reqres.in/api/users?page=1

{
  "page": 1,
  "per_page": 6,
  "total": 12,
  "total_pages": 2,
  "data": [
    {
      "id": 1,
      "email": "[email protected]",
      "first_name": "George",
      "last_name": "Bluth",
      "avatar": "https://reqres.in/img/faces/1-image.jpg"
    },
    {
      "id": 2,
      "email": "[email protected]",
      "first_name": "Janet",
      "last_name": "Weaver",
      "avatar": "https://reqres.in/img/faces/2-image.jpg"
    },
    {
      "id": 3,
      "email": "[email protected]",
      "first_name": "Emma",
      "last_name": "Wong",
      "avatar": "https://reqres.in/img/faces/3-image.jpg"
    },
    {
      "id": 4,
      "email": "[email protected]",
      "first_name": "Eve",
      "last_name": "Holt",
      "avatar": "https://reqres.in/img/faces/4-image.jpg"
    },
    {
      "id": 5,
      "email": "[email protected]",
      "first_name": "Charles",
      "last_name": "Morris",
      "avatar": "https://reqres.in/img/faces/5-image.jpg"
    },
    {
      "id": 6,
      "email": "[email protected]",
      "first_name": "Tracey",
      "last_name": "Ramos",
      "avatar": "https://reqres.in/img/faces/6-image.jpg"
    }
  ],
  "support": {
    "url": "https://reqres.in/#support-heading",
    "text": "To keep ReqRes free, contributions towards server costs are appreciated!"
  }
}

You can use FutureBuilder to wait for the API to complete and then show that the dropdown is ready.

The code below will do the trick. Take a look also at the live demo on DartPad.

Screenshots

ComponentNone selectedDropdown menuUser Selected
DropdownButtonNone selectedDropdown menuUser selected
ListViewNone selected-User selected
import 'dart:convert';

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class User {
  final int id;
  final String email;
  final String firstName;
  final String lastName;
  final String avatar;

  const User({
    required this.id,
    required this.email,
    required this.firstName,
    required this.lastName,
    required this.avatar,
  });

  User.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        email = json['email'],
        firstName = json['first_name'],
        lastName = json['last_name'],
        avatar = json['avatar'];
}

class UsersResponse {
  final int page;
  final int perPage;
  final int total;
  final int totalPages;
  final List<User> data;

  const UsersResponse({
    required this.page,
    required this.perPage,
    required this.total,
    required this.totalPages,
    required this.data,
  });

  UsersResponse.fromJson(Map<String, dynamic> json)
      : page = json['page'],
        perPage = json['per_page'],
        total = json['total'],
        totalPages = json['total_pages'],
        data = (json['data'] as List<dynamic>)
            .map((json) => User.fromJson(json))
            .toList();
}

class _MyHomePageState extends State<MyHomePage> {
  late Future<List<User>> _future;
  User? _selectedUser;
  var _currentIndex = 0;

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

  Future<List<User>> _getUsers() async {
    final response =
        await http.get(Uri.parse('https://reqres.in/api/users?page=1'));
    Map<String, dynamic> json = jsonDecode(response.body);
    final usersResponse = UsersResponse.fromJson(json);
    return usersResponse.data;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.list), label: 'Dropdown'),
          BottomNavigationBarItem(icon: Icon(Icons.list), label: 'ListView'),
        ],
        currentIndex: _currentIndex,
        onTap: (index) => setState(() => _currentIndex = index),
      ),
      body: Center(
        child: FutureBuilder<List<User>>(
            future: _future,
            builder: (context, snapshot) {
              if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              }

              if (snapshot.data == null) {
                return const CircularProgressIndicator();
              }

              return Padding(
                padding: const EdgeInsets.all(12.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: <Widget>[
                    const Text(
                      'Select user:',
                    ),
                    if (_currentIndex == 0)
                      SizedBox(
                        height: 64,
                        child: DropdownButton<User>(
                          onChanged: (user) =>
                              setState(() => _selectedUser = user),
                          value: _selectedUser,
                          items: [
                            ...snapshot.data!.map(
                              (user) => DropdownMenuItem(
                                value: user,
                                child: Row(
                                  children: [
                                    Image.network(user.avatar),
                                    Text('${user.firstName} ${user.lastName}'),
                                  ],
                                ),
                              ),
                            )
                          ],
                        ),
                      ),
                    if (_currentIndex == 1)
                      Expanded(
                        child: ListView.separated(
                          itemBuilder: (context, index) => ElevatedButton(
                            onPressed: () => setState(
                                () => _selectedUser = snapshot.data![index]),
                            style: identical(
                                    _selectedUser, snapshot.data![index])
                                ? ButtonStyle(
                                    backgroundColor: MaterialStateProperty.all(
                                        Colors.blue[400]),
                                    overlayColor: MaterialStateProperty.all(
                                        Colors.black12),
                                  )
                                : ButtonStyle(
                                    backgroundColor:
                                        MaterialStateProperty.all(Colors.white),
                                    overlayColor: MaterialStateProperty.all(
                                        Colors.black12),
                                  ),
                            child: Padding(
                              padding: const EdgeInsets.all(4.0),
                              child: Row(
                                children: [
                                  SizedBox(
                                      height: 64,
                                      child: Image.network(
                                          snapshot.data![index].avatar)),
                                  Text(
                                    '${snapshot.data![index].firstName} ${snapshot.data![index].lastName}',
                                    style: const TextStyle(color: Colors.black),
                                  ),
                                ],
                              ),
                            ),
                          ),
                          separatorBuilder: (context, _) =>
                              const SizedBox(height: 12),
                          itemCount: snapshot.data!.length,
                        ),
                      ),
                  ],
                ),
              );
            }),
      ),
    );
  }
}

JSON response from https://reqres.in/api/users?page=1

{
  "page": 1,
  "per_page": 6,
  "total": 12,
  "total_pages": 2,
  "data": [
    {
      "id": 1,
      "email": "[email protected]",
      "first_name": "George",
      "last_name": "Bluth",
      "avatar": "https://reqres.in/img/faces/1-image.jpg"
    },
    {
      "id": 2,
      "email": "[email protected]",
      "first_name": "Janet",
      "last_name": "Weaver",
      "avatar": "https://reqres.in/img/faces/2-image.jpg"
    },
    {
      "id": 3,
      "email": "[email protected]",
      "first_name": "Emma",
      "last_name": "Wong",
      "avatar": "https://reqres.in/img/faces/3-image.jpg"
    },
    {
      "id": 4,
      "email": "[email protected]",
      "first_name": "Eve",
      "last_name": "Holt",
      "avatar": "https://reqres.in/img/faces/4-image.jpg"
    },
    {
      "id": 5,
      "email": "[email protected]",
      "first_name": "Charles",
      "last_name": "Morris",
      "avatar": "https://reqres.in/img/faces/5-image.jpg"
    },
    {
      "id": 6,
      "email": "[email protected]",
      "first_name": "Tracey",
      "last_name": "Ramos",
      "avatar": "https://reqres.in/img/faces/6-image.jpg"
    }
  ],
  "support": {
    "url": "https://reqres.in/#support-heading",
    "text": "To keep ReqRes free, contributions towards server costs are appreciated!"
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文