listflutterdartfinalbloc

How to instantiate or add an item in a final List with copyWith?


What happens is that I have a class called Drawing with Equatable as follows :

class Drawing extends Equatable {
  final List<CanvasPath> canvasPaths;

  const Drawing({
    this.canvasPaths = const [],
  });

  @override
  List<Object?> get props => [canvasPaths];

  Drawing copyWith({
    List<CanvasPath>? canvasPaths,
  }) {
    return Drawing(
      canvasPaths: canvasPaths ?? this.canvasPaths,
    );
  }
}

I know I cannot initialize the list itself in the following way canvasPaths = newList; because it is final, however I use copyWith to attach it to the variable I have created in the following way :

class DrawingBloc extends Bloc<DrawingEvent, DrawingState> {

  // Variable global in Bloc, like cached
  final Drawing _drawing = const Drawing();

  DrawingBloc() : super(const DrawingState()) {
    on<StartDrawing>((event, emit) {
      // ! i cant do
      // _drawing.canvasPaths.add(event.canvasPath);
      // ! or
      // _drawing.canvasPaths.last = event.canvasPath;

      // Create a new list
      final newList = _drawing.canvasPaths.toList();

      newList.add(event.canvasPath);

      print(newList);

      _drawing.copyWith(
        canvasPaths: newList,
      ); // using the copyWith but when i print...

      print(_drawing);

      emit(state.copyWith(
        status: DrawingStatus.success,
        currentDrawing: _drawing.canvasPaths,
      ));
    });
  }
}

Result :

enter image description here

I would like to know why the copyWith does not show or does not work, I have to say that I use equatable because the list is compared.

But if I add it in the global class, it show this :

flutter Cannot add to an unmodifiable list


Solution

  • copyWith returns a new instance. it doesn't magically turn itself into a copy. so instead of

      print(newList);
    
      _drawing.copyWith(
        canvasPaths: newList,
      ); // using the copyWith but when i print...
    
      print(_drawing);
    

    you could maybe do

      print(newList);
    
      var newDrawing = _drawing.copyWith(
        canvasPaths: newList,
      ); // using the copyWith but when i print...
    
      print(newDrawing);
    

    Though that wouldn't help your situation probably. I'm not familiary with Equatable but couldn't you do

    this.canvasPaths = [],
    

    instead of

    this.canvasPaths = const [],
    

    or is it required to be a const? Because if you leave the const you could do

    _drawing.canvasPaths.add(event.canvasPath);
    

    just fine