简体   繁体   English

如何在flutter中传递变量并从API获取数据?

[英]How to pass variable and get data from API in flutter?

在此处输入图像描述

This the first UI in there when user enter channel name and after click join then should it pass "loadData" method in there that channel name should pass to "API" and get channelname and appId from that url.这是其中的第一个 UI,当用户输入频道名称并单击加入后,它是否应该在其中传递“loadData”方法,频道名称应传递给“API”并从url获取频道名称和appId

join button code加入按钮代码

  Future<void> onJoin() async {

    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => loadData(myController.text)),
    );
  }

loadData method加载数据方法

import 'dart:convert';
import 'package:http/http.dart';
import '../model/appIdModel.dart';


class ApiService {
  loadData(String myController) async {
    final String url =
        'https://telepulz.herokuapp.com/api/calls/?channel=$myController';

    Future<List<Data>> getData() async {
      Response response = await get(Uri.parse(url));
      if (response.statusCode == 2000) {
        Map<String, dynamic> json = jsonDecode(response.body);
        List<dynamic> body = json['data'];

        List<Data> datas = body.map((dynamic item) => Data.fromJson(item).toList();
            return datas;
            } else {
            throw ('cannot fetch data');
            }
        }
  }


}

Data model code数据model码

class Data {
  String appId;
  String channelName;

  Data({
    required this.appId,
    required this.channelName,
  });

  factory Data.fromJson(Map<String, dynamic> json) {
    return Data(
        appId: json['appId'] == null ? null : json['appId'],
        channelName: json['channelName'] == null ? null : json['channelName']);
  }
}

then appId and channelName should fetch然后appIdchannelName应该获取

FutureBuilder widget code show channelId and channelName (Home page code) FutureBuilder 小部件代码显示channelIdchannelName (主页代码)

class _MyHomePageState extends State<MyHomePage> {
  final myController = TextEditingController();
  bool _validateError = false;

  ApiService client = ApiService();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: SingleChildScrollView(
            clipBehavior: Clip.antiAliasWithSaveLayer,
            physics: BouncingScrollPhysics(),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Padding(padding: EdgeInsets.only(top: 20)),
                Padding(padding: EdgeInsets.symmetric(vertical: 20)),
                Container(
                  width: MediaQuery.of(context).size.width * 0.8,
                  child: TextFormField(
                    controller: myController,
                    decoration: InputDecoration(
                      labelText: 'Channel Name',
                      labelStyle: TextStyle(color: Colors.blue),
                      hintText: 'test',
                      hintStyle: TextStyle(color: Colors.black45),
                      errorText:
                          _validateError ? 'Channel name is mandatory' : null,
                      border: OutlineInputBorder(
                        borderSide: BorderSide(color: Colors.blue),
                        borderRadius: BorderRadius.circular(20),
                      ),
                      enabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(color: Colors.blue),
                        borderRadius: BorderRadius.circular(20),
                      ),
                      disabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(color: Colors.blue),
                        borderRadius: BorderRadius.circular(20),
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderSide: const BorderSide(color: Colors.blue),
                        borderRadius: BorderRadius.circular(20),
                      ),
                    ),
                  ),
                ),
                Padding(padding: EdgeInsets.symmetric(vertical: 30)),
                Container(
                  width: MediaQuery.of(context).size.width * 0.25,
                  child: MaterialButton(
                    onPressed: onJoin,
                    height: 40,
                    color: Colors.blueAccent,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: const <Widget>[
                        Text(
                          'Join',
                          style: TextStyle(color: Colors.white),
                        ),
                        Icon(
                          Icons.arrow_forward,
                          color: Colors.white,
                        ),
                      ],
                    ),
                  ),
                ),
                Center(
                  child: FutureBuilder(
                      future: client.getData(),
                      builder: (BuildContext context,
                          AsyncSnapshot<List<Data>> snapshot) {
                        if (snapshot.hasData) {
                          List<Data>? data = snapshot.data;
                          return ListView.builder(
                              itemBuilder: (context, index) => Column(
                                    children: [
                                      Text(
                                        data![index].channelName.toString(),
                                      ),
                                      Text(
                                        data[index].appId.toString(),
                                      ),
                                    ],
                                  ));
                        }
                        return const Center(
                          child: CircularProgressIndicator(),
                        );
                      }),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }

  Future<void> onJoin() async {
    setState(() {
      myController.text.isEmpty
          ? _validateError = true
          : _validateError = false;
    });

    // await _handleCameraAndMic(Permission.camera);
    // await _handleCameraAndMic(Permission.microphone);

    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => loadData(myController.text)),
    );
  }

this is the my code to fetch data.when I run the url with channel name then data show nicely.这是我获取数据的代码。当我运行带有频道名称的 url 时,数据会很好地显示。 在此处输入图像描述 I tired to fetch "channelName" and "appId" using this url. But show these errors.我厌倦了使用这个 url 获取“channelName”和“appId”。但显示这些错误。

at the join button method show this error在加入按钮方法中显示此错误

在此处输入图像描述

New error "ApiService" class show this error.新错误“ApiService”class 显示此错误。

在此处输入图像描述

How to resolve these errors and fetch appId and channelName?如何解决这些错误并获取 appId 和 channelName?

You are doing wrong when you call onJoin , change it to this:当您调用onJoin时,您做错了,将其更改为:

Future<void> onJoin() async {
  future = client.getData(myController.text);
}

then define new variable like this:然后像这样定义新变量:

Future<List<Data>>? future;

then change ApiService to this:然后将 ApiService 更改为:

class ApiService {

  final String url =
        'https://telepulz.herokuapp.com/api/calls/?channel=';
  Future<List<Data>> getData(String myController) async {
      Response response = await get(Uri.parse(url + myController));
      if (response.statusCode == 2000) {
        Map<String, dynamic> json = jsonDecode(response.body);
        List<dynamic> body = json['data'];

        List<Data> datas = body.map((dynamic item) => Data.fromJson(item).toList();
            return datas;
            } else {
            throw ('cannot fetch data');
            }
        }
}

then change your FutureBuilder to this然后将您的FutureBuilder更改为此

future != null ? FutureBuilder(//<--- add this
              future: future,
              builder:
                  (BuildContext context, AsyncSnapshot<List<Data>> snapshot) {
                if (snapshot.hasData) {
                  future = null; //<--- add this
                  List<Data>? data = snapshot.data;
                  return ListView.builder(
                      itemBuilder: (context, index) => Column(
                            children: [
                              Text(
                                data![index].channelName.toString(),
                              ),
                              Text(
                                data[index].appId.toString(),
                              ),
                            ],
                          ));
                }
                return const Center(
                  child: CircularProgressIndicator(),
                );
              }) : SizedBox(),//<--- add this

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM