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

问题描述 投票:0回答:1

我正在制作一个 pokemon go 应用程序,它将 pokemon 的屏幕截图作为输入,并根据它的一些属性创建一个小部件。除了 ListView.builder 之外,一切似乎都工作正常。以前的输入会变成小部件,并作为字符串列表存储在配置单元框中。当我添加照片时,我在当前会话中添加的前一个小部件将转换为最后一个小部件。这个问题一直持续到我重新启动应用程序为止。我不想使用 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,因为我看到它在其他帖子中使用,但这并没有改变任何内容。

flutter dart listview flutter-listview flutter-hive
1个回答
0
投票

问题不是 listView 而是字符串框列表。我创建了一个 Pokemon 类并开始将它们保存在数据库中。现在一切正常。

© www.soinside.com 2019 - 2024. All rights reserved.