Моя карта не обновляется после добавления нового элемента с помощью метода putifAbsent - PullRequest
0 голосов
/ 15 февраля 2020

Моя карта не принимает никаких новых значений, которые я добавляю к ней. Это мой провайдер:

import 'package:flutter/material.dart';

import '../classes/transaction.dart';




class Transactions with ChangeNotifier {

  Map<String, Transaction> _userTransactions = {

   'ju': Transaction(amount: 45, date: DateTime.now(), title: 'socks', accountType: 'timr', notes: 'joa' , icon: Icon(Icons.today,), id: 'kololdcd', repeat: 'always')
  } ;
  
   
 Map<String, Transaction> get userTransactions {
   print (_userTransactions);
   return {..._userTransactions};
   
 }
 


   void addNewTransaction({String txTitle, double txAmount, DateTime chosenDate,
      String txAccountType, String txNotes, String txRepeat, Icon txIcon, String txId}) {
     
    
    if (txRepeat != 'Einmalig' && _userTransactions.containsKey(txId)){
    _userTransactions.update(txId, (existingItem) =>  Transaction(
      title: existingItem.title,
      amount: existingItem.amount,
      date: DateTime.now(),
      id: DateTime.now().toString(),
      accountType: existingItem.accountType,
      notes: existingItem.notes,
      repeat: existingItem.repeat,
      icon: existingItem.icon,
    ) );
    
    } else {
      _userTransactions.putIfAbsent(txId, ()=>  Transaction(
      title: txTitle,
      amount: txAmount,
      date: chosenDate,
      id: DateTime.now().toString(),
      accountType: txAccountType,
      notes: txNotes,
      repeat: txRepeat,
      icon: txIcon,
    ));

    }
    //final cant be changed anymore
    print (_userTransactions);
    notifyListeners();
    
  }
  
  
 


}
Это мой слушатель:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../providers/transactions.dart';

import 'package:intl/intl.dart';


class TransactionList extends StatelessWidget {
 

  @override
  Widget build(BuildContext context) {
   final transactionsData = Provider.of<Transactions>(context);
   final transactions = transactionsData.userTransactions;
   print (transactions);
 
    return transactionsData.userTransactions.isEmpty
        ? LayoutBuilder(builder: (ctx, constraints) {
            return Column(
              children: <Widget>[
                Text(
                  'Keine Transaktionen hinzugefügt. ',
                  style: Theme.of(context).textTheme.title,
                ),
                const SizedBox(height: 20),
                Container(
                  height: constraints.maxHeight * 0.6,
                
                ),
              ],
            );
          })
        : 
       
                 
                                     ListView.builder(
                 itemCount: transactions.length,     
                 itemBuilder:(context, i) {
                    String key = transactions.keys.elementAt(i);
                   return Card(
      color: Colors.transparent,
      elevation: 0,
      margin: const EdgeInsets.symmetric(
        vertical: 8,
        horizontal: 5,
      ),
      child: ListTile(
        leading: CircleAvatar(
          backgroundColor: Colors.transparent,
          radius: 30,
          child: Padding(
            padding: const EdgeInsets.all(6),
            child: FittedBox(
              child: Text('\$${transactions[key].amount}'),
            ),
          ),
        ),
        title: Text(
          transactions[key].title,
          style: Theme.of(context).textTheme.title,
        ),
        subtitle: Text(
           DateFormat.yMMMd().format(transactions[key].date),
        ),
      
      ),

    );}
                  );
  }
}
Я вызываю этот метод провайдера с другого экрана:

void _submitData() {
    
    if (_amountController.text.isEmpty) {
      return;
    }

    final enteredTitle = _titleController.text;
    final enteredAmount = double.parse(_amountController.text);
    final enteredAccount = _accountController.text;
    final enteredNotes = _notesController.text;
    final enteredRepeat = _repeatController.text;
    final enteredIcon = Icon(MyIcon.paying);
    var uuid = Uuid(options: {});

    if (enteredTitle.isEmpty ||
        enteredAmount <= 0 ||
        _selectedDate == null ||
        enteredAccount.isEmpty ||
        enteredRepeat.isEmpty) {
      return; 
    } else {
      Transactions().addNewTransaction(
        txTitle: enteredTitle,
        txAmount: enteredAmount,
        chosenDate: _selectedDate,
        txAccountType: enteredAccount,
        txNotes: enteredNotes,
        txRepeat: enteredRepeat,
        txIcon: enteredIcon,
        txId: uuid.v1(options: {
          'node': [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
          'clockSeq': 0x1234,
          'mSecs': DateTime.now().millisecondsSinceEpoch,
          'nSecs': 5678
        }),
      );
    }
    Navigator.of(context).pop(context);
   
  }

Если я добавлю новую пару на карту, она будет показана в addTransactionMethod (оператор Print дает мне значения нового элемента). Но, как вы можете видеть в операторе печати userTransactions, моя карта _userTransactions не принимает новое значение, она сохраняет только предварительно заданное мной значение.

Это консоль отладчика (первый оператор печати взят из метода addTransaction - второй напрямую из карты userTransaction:

I / flutter (5636): {ju: {kololdcd) , socks, 2020-02-14 22: 33: 09.616563, timr, joa, всегда, Icon (IconData (U + 0E8DF)), 45.0}, ho: {2020-02-14 22: 33: 09.621559, почему бы и нет, 2019-02-11 00: 00: 00.000, jes, круто, всегда, Icon (IconData (U + 0E80D)), 78.0}}

I / флаттер (5636): {ju: {kololdcd, носки , 2020-02-14 22: 32: 14.896756, тимр, джоа, всегда, Icon (IconData (U + 0E8DF)), 45.0}}

Как видно, второй элемент отсутствует во втором отпечатке .

Как вы видите на картинке, новое значение не добавлено на карту

Как я могу решить проблему? Я просто хочу добавить элементы в this _userTransactions.

Хотелось бы услышать некоторые предложения:)

1 Ответ

1 голос
/ 15 февраля 2020

Проблема в том, что ваш классный виджет StatelessWidget. Вы не можете обновить StatelessWidget, потому что возможность его обновления означает, что у него есть состояние, которое можно обновить. Для вашего подхода вам придется изменить свой виджет на состояние с сохранением состояния:

class TransactionList extends StatefulWidget {
  TransactionList({Key key}) : super(key);

  @override
  State get createState => _TransactionListState();
}

class _TransactionListState extends State<TransactionList> {
  @override
  Widget build(BuildContext context) {
    ...
  }
}

Альтернативное решение, которое позволит вам оставить свой виджет как StatelessWidget (что в любом случае рекомендуется), вместо этого Для непосредственного вызова Provider.of вы используете Consumer для автоматического извлечения данных поставщика в метод компоновщика. Consumer также будет обрабатывать восстановление вашего виджета в случае обновления объекта транзакций.

class TransactionList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<Transactions>(
      builder: (context, transactionsData, _) {
        ...
      },
    );
  }
}
...