dart 如何从返回JSON的API调用动态加载PlutoGrid?

zf9nrax1  于 2023-07-31  发布在  其他
关注(0)|答案(2)|浏览(131)

我在将数据动态加载到PlutoGrid时遇到了问题。

  • 我没有收到任何错误消息。*

我确保从API获取的JSON数据填充了一个字符串列表,该列表Map到PlutoRow对象列表。当我静态地填充一个字符串列表并将其Map到PlutoRow对象列表时,它将显示在PlutoGrid中。当我一步一步地浏览我的代码时,我注意到以下几点:

  1. Widgetbuild()函数首先执行,并且rowsProviders列表对象为空
    1.接下来执行initiState()函数,并填充rowsProviders列表对象(已验证)
  2. Widgetbuild()函数再次执行,当我将PlutoGrid的rows属性设置为rowsProviders列表对象时,它现在有了数据。**它有它的列标题,但它没有行,也没有错误消息。
    我在下面提供了代码。我把所有东西都拆了除了这个PlutoGrid这是我正在调试的代码。
import 'dart:convert';
import 'package:http/http.dart' as http;
import "package:flutter/material.dart";
import 'package:pluto_grid/pluto_grid.dart';

const String API_URL_LLMT_PROVIDER_ROUTE = "http://127.0.0.1:5000/get_mt_providers";

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

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

    @override
    Widget build(BuildContext context) 
    {
        return MaterialApp
        (
            title: 'LL Translate',
            theme: ThemeData(primarySwatch: Colors.blue,),
            home: const DetectorPage(title: 'LLTS MT Tools'),
            debugShowCheckedModeBanner: true,
        );
    }
}

class DetectorPage extends StatefulWidget 
{
    const DetectorPage({Key? key, required this.title}) : super(key: key);
    final String title;

    @override
    State<DetectorPage> createState() => _DetectorPageState();
}

class _DetectorPageState extends State<DetectorPage>
{
    final List<PlutoColumn> columnsProviders = [];
    List<PlutoRow> rowsProviders = [];
    List<String> providers = [];
    
    @override
    void initState()
    {
        super.initState();

        columnsProviders.addAll 
        (
            [
                PlutoColumn
                (
                    width: 400,
                    backgroundColor: Colors.blue,
                    title: 'MT Provider',
                    field: 'MT Provider Tested',                        
                    type: PlutoColumnType.text(),
                    enableRowChecked: true,
                ),
                PlutoColumn
                (
                    width: 95,
                    backgroundColor: Colors.blue,
                    title: 'WER', 
                    field: 'Leven',
                    type: PlutoColumnType.text(),
                    enableFilterMenuItem: true,
                    textAlign: PlutoColumnTextAlign.center,
                    titleTextAlign: PlutoColumnTextAlign.center,
                ),
                PlutoColumn
                (
                    width: 100,
                    backgroundColor: Colors.blue,
                    title: 'BLEU',
                    field: 'BLEU',
                    type: PlutoColumnType.text(),
                    enableFilterMenuItem: false,
                    textAlign: PlutoColumnTextAlign.center,
                    titleTextAlign: PlutoColumnTextAlign.center,
                ),
                PlutoColumn
                (
                    width: 120,
                    backgroundColor: Colors.blue,
                    title: 'Combined',
                    field: 'Combined',
                    type: PlutoColumnType.text(),
                    enableFilterMenuItem: false,
                    textAlign: PlutoColumnTextAlign.center,
                    titleTextAlign: PlutoColumnTextAlign.center,
                ),
            ]
        );

        loadMtProviders();
    }

    void loadMtProviders() async 
    {
        // List<String> providersList = providers.cast<String>().toList();
        // List<String> providers = ['Google', 'Microsoft'];
        // List<String> providers = await getMtProviders();
        // providers = ['Google', 'Microsoft'];
        providers = await getMtProviders();

        rowsProviders = providers.map((item) 
        {
            return PlutoRow
            (
                cells: 
                {
                    'MT Provider Tested': 
                        PlutoCell
                        (
                            value: item,
                            
                        ), 
                    'Leven': PlutoCell(value: ''),
                    'BLEU': PlutoCell(value: ''),
                    'Combined': PlutoCell(value: ''),
                },
            );
        }).toList();

        setState(() 
        {

        });
    }
    
    Future<List<String>> getMtProviders() async 
    {
        var url = Uri.parse(API_URL_LLMT_PROVIDER_ROUTE);
        var response = await http.get(url);

        if (response.statusCode == 200)
        {
            var value = response.body;
            var jsonResponse = jsonDecode(value);

            List<String> result = jsonResponse.cast<String>();
            
            return result;
        } 
        else 
        {
            print('Request failed with status: ${response.statusCode}.');
            return ['0'];
        }
    }

    @override
    Widget build(BuildContext context) 
    {
        return Scaffold
        (
            body: SizedBox
            (
                child: PlutoGrid
                (
                    columns: columnsProviders,
                    rows: rowsProviders,
                ),
            ) 

        );
    }
}

字符串
先谢谢你。

d6kp6zgx

d6kp6zgx1#

正如我所假设的问题是关于数据没有得到更新。你需要对API调用使用一些状态管理,并在这类问题上更新UI元素。在我的决心中,我用了肘。你可以读一些articles
简而言之,cubit执行一些操作(这需要一些有限的时间)并发出一个状态,该状态将被BlocProvider,BlocListener,BlocBuilder等小部件捕获。它将显示一些所需的Widget
所以你的getMtProviders()和loadMtProviders()函数将像下面这样移动到库位:

class FetchDataCubit extends Cubit<FetchDataState> {
  FetchDataCubit() : super(FetchDataInitial());

  void fetchData() async {
    emit(FetchingData());
    List<String> providers = [];

    try {
      providers = await getMtProviders();
    } catch (e) {
      emit(FetchingDataError());
    }

    List<PlutoRow> rowsProviders = providers.map((item) {
      return PlutoRow(
        cells: {
          'MT Provider Tested': PlutoCell(
            value: item,
          ),
          'Leven': PlutoCell(value: ''),
          'BLEU': PlutoCell(value: ''),
          'Combined': PlutoCell(value: ''),
        },
      );
    }).toList();

    emit(FetchedData(rowsProviders));
  }

  Future<List<String>> getMtProviders() async {
    var url = Uri.parse(
        'https://cat-fact.herokuapp.com/facts/random?animal_type=cat&amount=10');
    var response = await http.get(url);
    if (response.statusCode == 200) {
      var value = response.body;
      List<dynamic> jsonResponse = jsonDecode(value);

      List<String> result =
          jsonResponse.map((e) => e['text'].toString()).toList();

      return result;
    } else {
      print('Request failed with status: ${response.statusCode}.');
      return ['0'];
    }
  }
}

字符串
将调用此fetchData函数。并将发出FetchedData()状态。其他腕尺状态如下:

@immutable
abstract class FetchDataState {}

class FetchDataInitial extends FetchDataState {}

class FetchingData extends FetchDataState {}

class FetchingDataError extends FetchDataState {}

class FetchedData extends FetchDataState {
  final List<PlutoRow> data;

  FetchedData(this.data);
}


你的有状态类将是:

class DetectorPage extends StatefulWidget {
  const DetectorPage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<DetectorPage> createState() => _DetectorPageState();
}

class _DetectorPageState extends State<DetectorPage> {
  final List<PlutoColumn> columnsProviders = [];
  final FetchDataCubit _fetchDataCubit = FetchDataCubit();

  @override
  void initState() {
    super.initState();
    _fetchDataCubit.fetchData();  // <- calling cubit function which will fetch the data.
    columnsProviders.addAll([
     // your code for adding columns 
    ]);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
      child: BlocBuilder(
        bloc: _fetchDataCubit,
        builder: (context, state) {
          if (state is FetchingData) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          } else if (state is FetchedData) {
            return PlutoGrid(
              columns: columnsProviders,
              rows: state.data,
            );
          } else if (state is FetchingDataError) {
            const Center(
              child: Text('Some Error occurred in fetching data'),
            );
          }
          return const SizedBox.shrink();
        },
      ),
    ));
  }
}


正如我在这里所说的BlocBuilder在那里,它将根据我们已经采取并作为_fetchDataCubit传递给它的cubit发出的状态显示小部件。


的数据
请更改API url。
希望这对你有所帮助,学习愉快

omqzjyyz

omqzjyyz2#

正如@pixel所指出的,这是关于Flutter中的状态管理。一种简单的方法是使用StateManager对象。PlutoGrid实际上有一个PlutoGridStateManager类用于此目的。
首先在PageState类中定义它:

class _DetectorPageState extends State<DetectorPage>
{
    late PlutoGridStateManager stateManagerProviders;
    ...
}

字符串
然后,当你填充网格时,你将它添加到PlutoGridStateManager:

setState(() 
{
    stateManagerProviders.appendRows(rowsProviders);
});


最后,您将PlutoGrid事件连接到PlutoGridStateManager,如下所示:

@override
Widget build(BuildContext context) 
{
    ...

    child: PlutoGrid
    (
        columns: columnsProviders,
        rows: rowsProviders,
        onLoaded: (PlutoGridOnLoadedEvent event) 
        {
            stateManagerProviders = event.stateManager;
            stateManagerSummary.setSelectingMode(PlutoGridSelectingMode.row);
        },
    ),
}


这是一个简单的例子。您可以通过在这里连接其他事件来维护PlutoGrid的状态。

相关问题