Flutter 变量在不同屏幕之间的无效传递

Flutter 变量在不同屏幕之间的无效传递,flutter,dart,google-cloud-firestore,Flutter,Dart,Google Cloud Firestore,我目前正在开发一个手指拼写学习应用程序。在fingerspelling\u screen.dart文件中,用户可以选择他/她想先学习的类别。当用户选择其中一个按钮时,应用程序将查询Firebase Firestore以获取标志对象列表,其中包含标志名称、标志所属类别以及每个标志的视频URL,然后将用户导航到视频播放器sign\u video.dart。从那里,用户可以按“下一步”切换到类别中的下一个标志。当用户按下check sign按钮时,用户将导航到checksign\u checker.d

我目前正在开发一个手指拼写学习应用程序。在fingerspelling\u screen.dart文件中,用户可以选择他/她想先学习的类别。当用户选择其中一个按钮时,应用程序将查询Firebase Firestore以获取标志对象列表,其中包含标志名称、标志所属类别以及每个标志的视频URL,然后将用户导航到视频播放器sign\u video.dart。从那里,用户可以按“下一步”切换到类别中的下一个标志。当用户按下check sign按钮时,用户将导航到checksign\u checker.dart以检查他们是否正确执行签名

我一直在使用构造函数将“category”变量从一个屏幕传递到另一个屏幕,我认为这不是很有效。我有办法解决这个问题吗

我希望在initState中初始化vidlist变量(一个存储符号对象列表的变量),因为需要首先初始化视频播放器控制器。我尝试使用StreamProvider,但由于某些原因,无法在initState中初始化vidlist变量。vidlist变量将始终为空

多谢各位

fingerspelling.dart

import 'package:slem_proto/screens/sign_video.dart';
import 'package:slem_proto/shared/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:undraw/undraw.dart';

class FingerspellingScreen extends StatelessWidget {
  static String routeName = 'fingerspelling_screen';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: EdgeInsets.only(left: 20, right: 20, top: 50),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Fingerspelling',
              style: kHeadingTextStyle,
            ),
            SizedBox(height: 30),
            FingerspellingTab(
              title: 'Alphabets',
              illustration: UnDrawIllustration.learning,
              onTap: () {
                print('Alphabet tab tapped');
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => SignVideoScreen(
                      category: 'alphabets',
                    ),
                  ),
                );
              },
            ),
            SizedBox(
              height: 15,
            ),
            FingerspellingTab(
              title: 'Numbers',
              illustration: UnDrawIllustration.calculator,
              onTap: () {
                print('Number tab tapped');
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => SignVideoScreen(
                      category: 'numbers',
                    ),
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

class FingerspellingTab extends StatelessWidget {
  final String title;
  final UnDrawIllustration illustration;
  final Function onTap;

  const FingerspellingTab(
      {@required this.title,
      @required this.illustration,
      @required this.onTap});

  @override
  Widget build(BuildContext context) {
    return InkWell(
      child: Container(
        width: double.infinity,
        height: 250,
        decoration: BoxDecoration(
          color: Color.fromRGBO(58, 139, 238, 0.2),
          borderRadius: BorderRadius.circular(20),
        ),
        child: Padding(
          padding: const EdgeInsets.only(left: 20, top: 20),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                title,
                style: kHeadingTextStyle.copyWith(
                  color: Color.fromRGBO(80, 80, 80, 0.8),
                  fontSize: 25,
                ),
              ),
              SizedBox(
                height: 15,
              ),
              Container(
                height: 150,
                child: UnDraw(
                  color: Color(0xFF6C63FF),
                  illustration: illustration,
                  placeholder: Text(
                      "Illustration is loading..."), //optional, default is the CircularProgressIndicator().
                ),
              ),
            ],
          ),
        ),
      ),
      onTap: onTap,
    );
  }
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:slem_proto/models/sign.dart';

class DatabaseService {
  // collection reference
  final CollectionReference signCollection =
      FirebaseFirestore.instance.collection('signs');

  // Sign list from snapshot
  List<Sign> _signListFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.docs.map((doc) {
      return Sign(
        category: doc.data()['category'] ?? '',
        sign_name: doc.data()['sign_name'] ?? '',
        sign_url: doc.data()['sign_url'] ?? '',
      );
    }).toList();
  }

  // get signs stream
  Stream<List<Sign>> get signs {
    return signCollection.snapshots().map(_signListFromSnapshot);
  }

  // get signs stream
  Stream<List<Sign>> getSignFromCategory({String category}) {
    return signCollection
        .where('category', isEqualTo: category)
        .snapshots()
        .map(_signListFromSnapshot);
  }
}

import 'dart:convert';
import 'dart:io';

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

class SignChecker extends StatefulWidget {
  final String category;
  SignChecker({this.category});

  @override
  _SignCheckerState createState() => _SignCheckerState(category: this.category);
}

class _SignCheckerState extends State<SignChecker> {
  final String category;
  _SignCheckerState({this.category});

  File _image;
  bool predictionStarted = false;
  bool predictionComplete = false;
  var predictionResult = 'Please wait...';

  Future getImage() async {
    setState(() {
      predictionStarted = false;
      predictionComplete = false;
    });

    // Get image from camera
    // var image = await ImagePicker.pickImage(source: ImageSource.camera);

    // Get image from gallery
    var image = await ImagePicker.pickImage(source: ImageSource.gallery);
    setState(() {
      _image = image;
      predictionStarted = true;
    });

    // Base64 Encode the image
    List<int> imageBytes = image.readAsBytesSync();
    String base64Image = base64.encode(imageBytes);

    // Print the base64 encoded string in console
    print(base64Image);

    // Send the encoded image with POST request
    Map<String, String> headers = {"Accept": "application/json"};
    Map body = {"image": base64Image};

    
    // var response = await http.post('http://XX.XXX.XXX.X/automl.php',
    //     body: body, headers: headers);
    var response = await http.post('http://XX.XXX.XXX.X/automl_alphabet.php',
        body: body, headers: headers);

    // Print the status code returned by server
    print('Status code');
    print(response.statusCode);

    // Get prediction Result
    setState(() {
      predictionResult = response.body;
      predictionComplete = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Sign Checker'),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            SizedBox(
              height: 20,
            ),
            Text(
              'Push the camera button',
              textAlign: TextAlign.center,
            ),
            RaisedButton(
              onPressed: getImage,
              child: Text('Camera'),
            ),
            (_image != null)
                ? Image.file(
                    _image,
                    scale: 50,
                  )
                : Text('No Image Picked'),
            predictionBody()
          ],
        ),
      ),
    );
  }

  Widget predictionBody() {
    var predictionText = (predictionComplete) ? 'Result' : 'Prediction started';
    if (predictionStarted) {
      return Column(
        children: <Widget>[
          Divider(),
          Text(predictionText),
          Text(predictionResult)
        ],
      );
    } else {
      return Container();
    }
  }
}
class Sign {
  final String category;
  final String sign_name;
  final String sign_url;
  Sign({this.category, this.sign_name, this.sign_url});
}
数据库。dart

import 'package:slem_proto/screens/sign_video.dart';
import 'package:slem_proto/shared/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:undraw/undraw.dart';

class FingerspellingScreen extends StatelessWidget {
  static String routeName = 'fingerspelling_screen';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: EdgeInsets.only(left: 20, right: 20, top: 50),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Fingerspelling',
              style: kHeadingTextStyle,
            ),
            SizedBox(height: 30),
            FingerspellingTab(
              title: 'Alphabets',
              illustration: UnDrawIllustration.learning,
              onTap: () {
                print('Alphabet tab tapped');
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => SignVideoScreen(
                      category: 'alphabets',
                    ),
                  ),
                );
              },
            ),
            SizedBox(
              height: 15,
            ),
            FingerspellingTab(
              title: 'Numbers',
              illustration: UnDrawIllustration.calculator,
              onTap: () {
                print('Number tab tapped');
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => SignVideoScreen(
                      category: 'numbers',
                    ),
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

class FingerspellingTab extends StatelessWidget {
  final String title;
  final UnDrawIllustration illustration;
  final Function onTap;

  const FingerspellingTab(
      {@required this.title,
      @required this.illustration,
      @required this.onTap});

  @override
  Widget build(BuildContext context) {
    return InkWell(
      child: Container(
        width: double.infinity,
        height: 250,
        decoration: BoxDecoration(
          color: Color.fromRGBO(58, 139, 238, 0.2),
          borderRadius: BorderRadius.circular(20),
        ),
        child: Padding(
          padding: const EdgeInsets.only(left: 20, top: 20),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                title,
                style: kHeadingTextStyle.copyWith(
                  color: Color.fromRGBO(80, 80, 80, 0.8),
                  fontSize: 25,
                ),
              ),
              SizedBox(
                height: 15,
              ),
              Container(
                height: 150,
                child: UnDraw(
                  color: Color(0xFF6C63FF),
                  illustration: illustration,
                  placeholder: Text(
                      "Illustration is loading..."), //optional, default is the CircularProgressIndicator().
                ),
              ),
            ],
          ),
        ),
      ),
      onTap: onTap,
    );
  }
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:slem_proto/models/sign.dart';

class DatabaseService {
  // collection reference
  final CollectionReference signCollection =
      FirebaseFirestore.instance.collection('signs');

  // Sign list from snapshot
  List<Sign> _signListFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.docs.map((doc) {
      return Sign(
        category: doc.data()['category'] ?? '',
        sign_name: doc.data()['sign_name'] ?? '',
        sign_url: doc.data()['sign_url'] ?? '',
      );
    }).toList();
  }

  // get signs stream
  Stream<List<Sign>> get signs {
    return signCollection.snapshots().map(_signListFromSnapshot);
  }

  // get signs stream
  Stream<List<Sign>> getSignFromCategory({String category}) {
    return signCollection
        .where('category', isEqualTo: category)
        .snapshots()
        .map(_signListFromSnapshot);
  }
}

import 'dart:convert';
import 'dart:io';

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

class SignChecker extends StatefulWidget {
  final String category;
  SignChecker({this.category});

  @override
  _SignCheckerState createState() => _SignCheckerState(category: this.category);
}

class _SignCheckerState extends State<SignChecker> {
  final String category;
  _SignCheckerState({this.category});

  File _image;
  bool predictionStarted = false;
  bool predictionComplete = false;
  var predictionResult = 'Please wait...';

  Future getImage() async {
    setState(() {
      predictionStarted = false;
      predictionComplete = false;
    });

    // Get image from camera
    // var image = await ImagePicker.pickImage(source: ImageSource.camera);

    // Get image from gallery
    var image = await ImagePicker.pickImage(source: ImageSource.gallery);
    setState(() {
      _image = image;
      predictionStarted = true;
    });

    // Base64 Encode the image
    List<int> imageBytes = image.readAsBytesSync();
    String base64Image = base64.encode(imageBytes);

    // Print the base64 encoded string in console
    print(base64Image);

    // Send the encoded image with POST request
    Map<String, String> headers = {"Accept": "application/json"};
    Map body = {"image": base64Image};

    
    // var response = await http.post('http://XX.XXX.XXX.X/automl.php',
    //     body: body, headers: headers);
    var response = await http.post('http://XX.XXX.XXX.X/automl_alphabet.php',
        body: body, headers: headers);

    // Print the status code returned by server
    print('Status code');
    print(response.statusCode);

    // Get prediction Result
    setState(() {
      predictionResult = response.body;
      predictionComplete = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Sign Checker'),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            SizedBox(
              height: 20,
            ),
            Text(
              'Push the camera button',
              textAlign: TextAlign.center,
            ),
            RaisedButton(
              onPressed: getImage,
              child: Text('Camera'),
            ),
            (_image != null)
                ? Image.file(
                    _image,
                    scale: 50,
                  )
                : Text('No Image Picked'),
            predictionBody()
          ],
        ),
      ),
    );
  }

  Widget predictionBody() {
    var predictionText = (predictionComplete) ? 'Result' : 'Prediction started';
    if (predictionStarted) {
      return Column(
        children: <Widget>[
          Divider(),
          Text(predictionText),
          Text(predictionResult)
        ],
      );
    } else {
      return Container();
    }
  }
}
class Sign {
  final String category;
  final String sign_name;
  final String sign_url;
  Sign({this.category, this.sign_name, this.sign_url});
}

首先,使用构造函数传递变量可能不是低效的,因为颤振只传递引用。说

那么第二条线就不贵了

其次,如果您询问有关状态管理的问题,您可以尝试
Mobx
Bloc
Redux
,等等。有很多方法可以做到这一点