flutter ListView.builder无法与hive数据库正常工作

oogrdqng  于 2023-10-22  发布在  Flutter
关注(0)|答案(1)|浏览(116)

我正在做一个口袋妖怪去应用程序,需要作为输入的口袋妖怪截图,并从它的一些属性创建一个小部件。除了ListView. builder之外,一切都正常工作。以前的输入被转换为小部件,小部件作为字符串列表存储在Hive框中。当我添加照片以前的小部件,我在当前会话中添加转换成最后一个。这个问题一直持续到我重新启动应用程序。我不想使用setState作为解决方案,因为我知道它不是最佳的。感谢您的帮助!
https://imgur.com/a/2zmgnEu第四张图片是重新启动应用程序后发生的事情,第五张是口袋妖怪的示例截图。不要介意StunkFisk的身高。

import 'package:flutter/material.dart';
import 'package:pokemon_app/main_screen.dart';
import 'package:hive_flutter/hive_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Hive.initFlutter();
  await Hive.openBox<List<String>>('pokeBox');
  runApp(
    const MyApp(),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MainScreen(),
    );
  }
}
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:pokemon_app/provider/poke_provider.dart';
import 'package:pokemon_app/poke_card/poke_class.dart';

class MainScreen extends StatefulWidget {
  const MainScreen({super.key});
  @override
  State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {

  late final pokeProvider;

  @override
  void initState() {
   pokeProvider = PokeProvider();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    var pokeBox = Hive.box<List<String>>('pokeBox');
    return Scaffold(
      appBar: AppBar(
        title: const Text('Main Screen'),
        actions: [
          IconButton(
            onPressed: () {
              pokeBox.clear();
              setState(() {});
            },
            icon: const Icon(Icons.delete),
          ),
          IconButton(
            onPressed: pokeProvider.getImageFromGallery,
            icon: const Icon(
              Icons.add_outlined,
              color: Colors.white,
            ),
          ),
        ],
      ),
      body: Center(
        child: ValueListenableBuilder<Box<List<String>>>(
          valueListenable: pokeBox.listenable(),
          builder: (context, pokeBox, _) {
            return pokeBox.isEmpty
                ? const Center(
                    child: Text(''),
                  )
                : ListView.builder(
                  itemCount: pokeBox.length,
                  padding: const EdgeInsetsDirectional.only(bottom: 8),
                  itemBuilder: (context, index) {
                    return PokeCard(
                      singlePokeList: pokeProvider.getFromBox(index),
                    );
                  },
                );
          },
        ),
      ),
    );
  }
}
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image/image.dart' as img;
import 'package:path_provider/path_provider.dart';
import 'package:hive_flutter/hive_flutter.dart';

class PokeProvider{
  final imagePicker = ImagePicker();
  
  late File? imagePath;
  late File croppedImageFile;
  final textRecognizer = TextRecognizer(script: TextRecognitionScript.latin);
  int x = 0;
  var pokeBox = Hive.box<List<String>>('pokeBox');
  List<String> pokeList = [
    'Name',
    'CP',
    'Height',
    'Weight'
  ]; //Limited size string, contents will be changed later. Variables will line like this.
  String pokeName = 'Name';
  String pokeCp = 'cp';
  String pokeHeight = 'Height';
  String pokeWeight = 'Weight';

  getImageFromGallery() async {
    final dummyImage = await imagePicker.pickImage(source: ImageSource.gallery);
    if (dummyImage == null) return;
    final imagePath = File(dummyImage.path);

    final Image image =
        Image(image: FileImage(imagePath)); // Getting image resolution for cropping desired part.
    Completer<ui.Image> completer = Completer<ui.Image>();
    image.image.resolve(const ImageConfiguration()).addListener(
      ImageStreamListener(
        (ImageInfo image, bool _) {
          completer.complete(image.image);
        },
      ),
    );

    ui.Image info = await completer.future;
    int width = info.width;     //taking images width and height to crop a spesific part
    int height = info.height;

    final imageBytes = img.decodeImage(imagePath.readAsBytesSync());
    final croppedImage = img.copyCrop(imageBytes!,
        x: 0,
        y: (height * 0.35).round(),
        width: width,
        height: (height * 0.15).round());

    final directory = await getTemporaryDirectory(); // for saving cropped images to temporary directory.
    final directoryPath = directory.path;            // so I can use text recognition on cropped image.

    final croppedImagePng = img.encodePng(croppedImage);
    croppedImageFile = await File(
            '$directoryPath/CroppedImageFile$x.png')
        .writeAsBytes(croppedImagePng);

    final croppedInputImage = InputImage.fromFile(croppedImageFile); // image recognition on whole image.
    final inputImage = InputImage.fromFile(imagePath);               // image recognition on cropped image.
    final RecognizedText recognizedText =
        await textRecognizer.processImage(inputImage);

    final RecognizedText croppedRecognizedText =
        await textRecognizer.processImage(croppedInputImage);

    for (TextBlock block in croppedRecognizedText.blocks) {         //to get pokemon name from the cropped image.
      for (TextLine line in block.lines) {                          // Its always on the first line so I break after one loop.
        pokeName = line.text;
        break;
      }
      break;
    }
    
    for (TextBlock block in recognizedText.blocks) { // I get other desired metrics here.
      for (TextLine line in block.lines) {
        if (line.text.contains('kg') ||
            line.text.contains('m') ||
            line.text.contains('CP') ||
            line.text.contains('DG')
            ) {
          if (line.text.contains('kg')) {
            pokeWeight = line.text;
          } else if (line.text.contains('m')) {
            pokeHeight = line.text;
          } else if (line.text.contains('CP') ||line.text.contains('DG')) {
            pokeCp = line.text;
          }
        }
      }
    }

    x++;
    putToBox(pokeName, pokeCp, pokeWeight, pokeHeight);
    textRecognizer.close();
  }

  void putToBox(String name, String cp, String weight, String height) {
    pokeList[0] = name;
    pokeList[1] = cp;
    pokeList[2] = weight;
    pokeList[3] = height;

    pokeBox.add(pokeList);
  }

  List<String> getFromBox(int index) {
    return pokeBox.getAt(index)!;
  }
}
class PokeCard extends StatelessWidget {
  const PokeCard(
      {super.key,
      required this.singlePokeList});

  /* final String name;
  final String combatPower;
  final String height;
  final String weight; */
  final List<String> singlePokeList;

  @override
  Widget build(BuildContext context) {
    Size screenSize = MediaQuery.of(context).size;
    return Container(
      margin: const EdgeInsets.only(bottom: 8),   
      decoration: BoxDecoration(
        color: Colors.amber.shade100,
        borderRadius: const BorderRadius.all(Radius.circular(15)),
      ),
      width: screenSize.width * 0.55,
      height: screenSize.height * 0.1,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Padding(
            padding: const EdgeInsets.all(12.0),
            child: Text(singlePokeList[0]),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: [
              Text(singlePokeList[1]), 
              //Divider(thickness: 5,color: Colors.black, height: 12),
              const VerticalDivider(),
              Text(singlePokeList[2]),
              const VerticalDivider(),
              Text(singlePokeList[3]),
            ],
          ),
        ],
      ),
    );
  }
}

我使用提供程序包,然后改为ValueListanableBuilder,因为我看到它被用于另一个职位,但这并没有改变任何东西。

vi4fp9gy

vi4fp9gy1#

问题不是listView,而是字符串列表框。我创建了一个口袋妖怪类,并开始保存他们在数据库中。现在一切正常

相关问题