Search code examples
flutterlistviewdartstream-builder

Listviewer in Streambuilder doesnt update the deleted objects correctly


When I delete an item from the listview, the listview shows me the wrong item. Although in the displayed map the correct element is deleted. Unfortunately, googling has yielded nothing. Can you understand how this happens?

I have tried an additional StreamBuilder for the ItemAddSingleIngredient widget among many other solutions, but I just don't understand how this happens.

before pressing delete enter image description here

After pressing delete enter image description here

The Streambuilder

StreamBuilder<Object>(
  stream: blocIngredient.outIngredientMap,
  builder:
      (BuildContext context, AsyncSnapshot snapshot) {
    String leerText = snapshot.hasError
        ? "Error im Snapshot --> UIRecipeMain.dart " +
            snapshot.error.toString()
        : "empty Ingredients-List";
    if (snapshot.hasData) {
      return Container(
        height: 150.0,
        // Change as per your requirement
        width: 500.0,
        // Change as per your require
        decoration: BoxDecoration(
            color: Colors.white38,
            border:
                Border.all(color: Colors.black38)),
        child: Align(
          alignment: Alignment.topCenter,
          child: Scrollbar(
            controller: _scrollControllerIngredient,
            isAlwaysShown: true,
            child: ListView.builder(
              controller: _scrollControllerIngredient,
              shrinkWrap: true,

              itemCount: blocIngredient
                  .repositoryIngredientMap
                  .IngredientObjectMap
                  .length,
              itemBuilder: (context, i) {
                String itemKey = blocIngredient
                    .repositoryIngredientMap
                    .IngredientObjectMap
                    .keys
                    .elementAt(i);

                return ItemAddSingleIngredient(
                  blocIngredient,
                  itemKey,
                );
              },
            ),
          ),
        ),
      );
    } else {
      return Center(
        child: Column(
          children: [
            Container(
              height: 150.0,
              // Change as per your requirement
              width: 500.0,
              color: Colors.white38,
              padding:
                  EdgeInsets.fromLTRB(20, 10, 20, 20),
              child: Text(
                leerText,
                style: TextStyle(
                  fontSize: 20.0,
                  fontWeight: FontWeight.w400,
                  color: Colors.white,
                ),
              ),
            ),
          ],
        ),
      );
    }
  },
),

ItemAddSingleIngredient

import 'package:allergy/Zutaten/BLoC/BlocIngredient.dart';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';

class ItemAddSingleIngredient extends StatefulWidget {
  final BlocIngredient blocIngredient;
  final String itemKey;

  ItemAddSingleIngredient(this.blocIngredient, this.itemKey);

  void initState() {}

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

class _ItemAddSingleIngredientState extends State<ItemAddSingleIngredient> {
  String zutat;

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          SizedBox(
            height: 5,
          ),
          Row(children: [
            SizedBox(
              width: 10,
            ),
            Expanded(
              flex: 1,
              child: Text(widget.blocIngredient.repositoryIngredientMap.IngredientObjectMap[widget.itemKey].name)),
            Expanded(
              flex: 7,
              child: TextFormField(
                style: TextStyle(
                  fontSize: 20.0,
                  fontWeight: FontWeight.w400,
                  color: Colors.black,
                ),
                decoration: InputDecoration(
                  contentPadding: new EdgeInsets.symmetric(
                      vertical: 10.0, horizontal: 10.0),
                  focusColor: Colors.white,
                  hintText: widget.itemKey,
                  hintStyle: TextStyle(fontSize: 15.0, color: Colors.black54),
                  suffixIcon: IconButton(
                    onPressed: () => null,
                    icon: Icon(Icons.qr_code_outlined),
                  ),
                  filled: true,
                  fillColor: Colors.white,
                  border: OutlineInputBorder(),
                ),
                onChanged: (String txt) => {

                  setState((){
                    widget.blocIngredient.repositoryIngredientMap
                        .IngredientObjectMap[widget.itemKey].name = txt;
                  })
                },
                validator: (String value) {
                  if (value.isEmpty) {
                    return "Zutat";
                  }
                  return null;
                },
              ),
            ),
            Expanded(
              flex: 1,
              child: IconButton(
                icon: Icon(Icons.delete_forever),
                onPressed: () =>
                setState((){
                  widget.blocIngredient.deleteIngredientItem(widget.itemKey);
                }),

              ),
            ),
            SizedBox(
              width: 10,
            ),
          ]),
          SizedBox(
            height: 5,
          ),
        ],
      ),
    );
  }
}

Unfortunately, I have not been working with Flutter for long. Therefore I am very happy about any help.


Solution

  • Upon some further research, I figured out what's the problem. Apparently, when you have multiple widgets of the same type and at the same level in the widget tree, there is a possibility that Flutter may not be able to correctly identify an object without a key (https://www.raywenderlich.com/22416843-unlocking-your-flutter-widgets-with-keys).

    The solution is simply to add a key for each item. There are different types of keys. I solved my problem by adding {key: UniqueKey()} parameter in creating each item.