Переменная «total» не обновляется

#android #ios #flutter

#Android #iOS #флаттер

Вопрос:

Итак, я создал приложение, которое определяет значение банкноты валюты, и каждый раз, когда обнаруживается валюта, ее значение должно обновляться в переменной «total». Например: предположим, я делаю снимок банкноты в 200 рупий, переменная «total» должна быть увеличена на 200, что она и делает. Теперь, если я сделаю снимок банкноты в 500 рупий, общая сумма должна быть 700 (200 500), но она показывает 500, что означает, что в ней не были сохранены предыдущие 200, и она снова вернулась к 0. Кто-нибудь, пожалуйста, помогите, это похоже на действительно небольшую ошибку, и я много пробовал, но тщетно.

     import 'dart:io';

import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:torch_compat/torch_compat.dart';
import 'package:flutter_tts/flutter_tts.dart';
import 'package:tflite/tflite.dart';

int total = 0;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final cameras = await availableCameras();
  final firstCamera = cameras.first;


  runApp(
    MaterialApp(
      theme: ThemeData.dark(),
      home: TakePictureScreen(
        // Pass the appropriate camera to the TakePictureScreen widget.
        camera: firstCamera,
      ),
    ),
  );
}

class TakePictureScreen extends StatefulWidget {
  final CameraDescription camera;
  const TakePictureScreen({
    Key key,
    @required this.camera,
  }) : super(key: key);

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

class _TakePictureScreenState extends State<TakePictureScreen> {
  CameraController _controller;
  Future<void> _initializeControllerFuture;

  @override
  void initState() {
    super.initState();
    // To display the current output from the Camera,
    // create a CameraController.
    _controller = CameraController(
      // Get a specific camera from the list of available cameras.
      widget.camera,
      // Define the resolution to use.
      ResolutionPreset.high,
    );

    // Next, initialize the controller. This returns a Future.
    _initializeControllerFuture = _controller.initialize();
  }

  @override
  void dispose() {
    // Dispose of the controller when the widget is disposed.
    _controller.dispose();
    TorchCompat.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Center(child: Text('Noteify'))),
      // Wait until the controller is initialized before displaying the
      // camera preview. Use a FutureBuilder to display a loading spinner
      // until the controller has finished initializing.
      body: FutureBuilder<void>(
        future: _initializeControllerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            // If the Future is complete, display the preview.
            return CameraPreview(_controller);
          } else {
            // Otherwise, display a loading indicator.
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          Center(
            child: Container(
              height: 100.0,
              width: 100.0,
              child: FittedBox(
                child: FloatingActionButton(
                  child: Icon(Icons.camera_alt),
                  // Provide an onPressed callback.
                  onPressed: () async {
                    // Take the Picture in a try / catch block. If anything goes wrong,
                    // catch the error.
                    try {
                      TorchCompat.turnOn();
                      // Ensure that the camera is initialized.
                      await _initializeControllerFuture;

                      // Construct the path where the image should be saved using the
                      // pattern package.
                      final path = join(
                        // Store the picture in the temp directory.
                        // Find the temp directory using the `path_provider` plugin.
                        (await getTemporaryDirectory()).path,
                        '${DateTime.now()}.png',
                      );

                      // Attempt to take a picture and log where it's been saved.
                      await _controller.takePicture(path);
                      TorchCompat.turnOff();

                      // If the picture was taken, display it on a new screen.
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) => DisplayPictureScreen(path),
                        ),
                      );
                    } catch (e) {
                      // If an error occurs, log the error to the console.
                      print(e);
                    }
                  },
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// A widget that displays the picture taken by the user.
class DisplayPictureScreen extends StatefulWidget {
  final String imagePath;
  DisplayPictureScreen(this.imagePath);
  @override
  _DisplayPictureScreenState createState() => _DisplayPictureScreenState();
}

class _DisplayPictureScreenState extends State<DisplayPictureScreen> {
  List op;
  Image img;

  @override
  void initState() {
    super.initState();
    loadModel().then((value) {
      setState(() {});
    });
    img = Image.file(File(widget.imagePath));
    classifyImage(widget.imagePath, total);
  }

  @override
  Widget build(BuildContext context) {
//    Image img = Image.file(File(widget.imagePath));
//    classifyImage(widget.imagePath, total);

    return Scaffold(
      appBar: AppBar(title: Text('Display the Picture')),
      // The image is stored as a file on the device. Use the `Image.file`
      // constructor with the given path to display the image.
      body: Container(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Expanded(child: Center(child: img)),
            SizedBox(
              height: 20,
            )
          ],
        ),
      ),
    );
  }

  Future<void> runTextToSpeech(String outputMoney, int totalMoney) async {
    FlutterTts flutterTts;
    flutterTts = new FlutterTts();

    if (outputMoney == "50 rupees") {
      String tot = totalMoney.toString();
      print(tot);
      String speakString = "Fifty rupees, Your total is now rupees, $tot";
      await flutterTts.setSpeechRate(0.3);
      await flutterTts.awaitSpeakCompletion(true);
      await flutterTts.speak(speakString);
    }
    if (outputMoney == "100 rupees") {
      String tot = totalMoney.toString();
      print(tot);
      String speakString = "One Hundred rupees, Your total is now rupees, $tot";
      await flutterTts.setSpeechRate(0.3);
      await flutterTts.awaitSpeakCompletion(true);
      await flutterTts.speak(speakString);
    }
    if (outputMoney == "200 rupees") {
      String tot = totalMoney.toString();
      print(tot);
      String speakString = "Two Hundred rupees, Your total is now rupees, $tot";
      await flutterTts.setSpeechRate(0.3);
      await flutterTts.awaitSpeakCompletion(true);
      await flutterTts.speak(speakString);
    }
    if (outputMoney == "500 rupees") {
      String tot = totalMoney.toString();
      print(tot);
      String speakString =
          "Five Hundred rupees, Your total is now rupees, $tot";
      await flutterTts.setSpeechRate(0.3);
      await flutterTts.awaitSpeakCompletion(true);
      await flutterTts.speak(speakString);
    }
    if (outputMoney == "2000 rupees") {
      String tot = totalMoney.toString();
      print(tot);
      String speakString =
          "Two thousand rupees, Your total is now rupees, $tot";
      await flutterTts.setSpeechRate(0.3);
      await flutterTts.awaitSpeakCompletion(true);
      await flutterTts.speak(speakString);
    }
  }

  classifyImage(String image, int total) async {
    var output = await Tflite.runModelOnImage(
      path: image,
      numResults: 5,
      threshold: 0.5,
      imageMean: 127.5,
      imageStd: 127.5,
    );

      op = output;

      if (op != null) {
        if (op[0]["label"] == "50 rupees") {
          total  = 50;
          runTextToSpeech("50 rupees", total);
        }
        if (op[0]["label"] == "100 rupees") {
          total  = 100;
          runTextToSpeech("100 rupees", total);
        }
        if (op[0]["label"] == "200 rupees") {
          total  = 200;
          runTextToSpeech("200 rupees", total);
        }
        if (op[0]["label"] == "500 rupees") {
          total  = 500;
          runTextToSpeech("500 rupees", total);
        }

        if (op[0]["label"] == "2000 rupees") {
          total  = 2000;
          runTextToSpeech("2000 rupees", total);
        }
      } else
        runTextToSpeech("No note found", total);
  }

  loadModel() async {
    await Tflite.loadModel(
      model: "assets/model_unquant.tflite",
      labels: "assets/labels.txt",
    );
  }

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

Ответ №1:

В качестве параметра у вас есть как глобальная переменная с именем total , так и локальная classifyImage функциональная переменная total . Когда вы total = 50; это делаете, по умолчанию ссылается на локальную переменную. По какой-то причине вы передаете глобальную переменную в свою classifyImage функцию, когда она совершенно не нужна.

Удалите total параметр из определения вашей функции.

 classifyImage(String image, int total) async {
  

Для

 classifyImage(String image) async {