从 MySQL 数据库中检索到的 flutter 应用程序中的自动刷新项目列表

Auto refreshing list of items in flutter application retrieved from MySQL database

我有一个 flutter 应用程序,我从 MySQL 数据库中检索数据(温度读数)。由于我每 30 秒获取一次新数据,我希望我的应用程序自动刷新屏幕,以便每次更新时自动显示新数据。我使用 getReadingList() 检索数据并仅在 initState() 方法中使用它。我知道可以每 30 秒调用一次 getReadingList(),但是有更有效的内置解决方案吗?

这是我到目前为止所做的:

// main.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import './models/readings.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Server',
      home: MyHomePage(title: 'Flutter Server App'),
    );
  }
}

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

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  late Future<List<Reading>> readings;

  Future<List<Reading>> getReadingList() async {
    final response = await http.get(
        Uri.parse('<MY_GET_REQUEST_LINK>')
    );
    final items = json.decode(response.body).cast<Map<String, dynamic>>();
    List<Reading> readings = items.map<Reading>((json) {
      return Reading.fromJson(json);
    }).toList();
    return readings;
  }

  @override
  void initState() {
    super.initState();
    readings = getReadingList(); // readings are retrieved here
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        centerTitle: true,
      ),
      body: Center(
        child: FutureBuilder<List<Reading>>(
        future: readings,
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (!snapshot.hasData) return CircularProgressIndicator();
          return ListView.builder(
            itemCount: snapshot.data.length,
            itemBuilder: (BuildContext context, int index) {
              var data = snapshot.data[index];
              return Text('${data.id}, ${data.temperature}°C, ${data.humidity}%, ${data.reading_time}');
            },
          );
        },
        ),
    ),);
  }
}
// readings.dart
import 'package:flutter/material.dart';

class Reading {
  final int? id;
  final double? temperature, humidity;
  final String? reading_time;

  Reading({this.id, this.temperature, this.humidity, this.reading_time});

  factory Reading.fromJson(Map<String, dynamic> json) {
    double convertedTemperature = double.parse(json['temperature']);
    double convertedHumidity = double.parse(json['humidity']);
    return Reading(
      id: json['id'],
      temperature: convertedTemperature,
      humidity: convertedHumidity,
      reading_time: json['reading_time'],
    );
  }
}

我给你做了一些安排。这可能是您正在寻找的解决方案之一。请问可以试试吗?

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Server',
      home: MyHomePage(title: 'Flutter Server App'),
    );
  }
}

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

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final StreamController<List<Reading>> readingStreamController = StreamController<List<Reading>>();

  void startStreamReadingList() async {
    Timer.periodic(
      Duration(seconds: 30),
      (timer) async {
        if (readingStreamController.isClosed) return timer.cancel();

        final response = await http.get(Uri.parse('<MY_GET_REQUEST_LINK>'));
        final items = json.decode(response.body).cast<Map<String, dynamic>>();

        List<Reading> readings = items.map<Reading>((json) {
          return Reading.fromJson(json);
        }).toList();

        readingStreamController.sink.add(readings);
      },
    );
  }

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

  @override
  void dispose() {
    readingStreamController.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        centerTitle: true,
      ),
      body: Center(
        child: StreamBuilder<List<Reading>>(
          stream: readingStreamController.stream,
          builder: (context, snapshot) {
            if (!snapshot.hasData) return CircularProgressIndicator();
            return ListView.builder(
              itemCount: snapshot.data!.length,
              itemBuilder: (context, index) {
                final data = snapshot.data![index];
                return Text('${data.id}, ${data.temperature}°C, ${data.humidity}%, ${data.reading_time}');
              },
            );
          },
        ),
      ),
    );
  }
}

class Reading {
  final int? id;
  final double? temperature, humidity;
  final String? reading_time;

  Reading({this.id, this.temperature, this.humidity, this.reading_time});

  factory Reading.fromJson(Map<String, dynamic> json) {
    final convertedTemperature = double.parse(json['temperature']);
    final convertedHumidity = double.parse(json['humidity']);
    return Reading(
      id: json['id'],
      temperature: convertedTemperature,
      humidity: convertedHumidity,
      reading_time: json['reading_time'],
    );
  }
}