2

right widget has gesterdetector that adds a String ("ZzZ") to List; left widget shows all String there in String list by List view Buildder,

right widget adds "ZzZ" to list after pressing the button successfully but it dosent sets ui state... in android studio after hot reload it shows all added "ZzZ"

import 'package:flutter/material.dart';

List<String> ListOfZzZ=[];

class homescreen extends StatefulWidget {
  @override
  _homescreenState createState() => _homescreenState();
}

class _homescreenState extends State<homescreen> {
  @override
  Widget build(BuildContext context) {
    return Material(
      child: Scaffold(
        body: Row(children: [
          Expanded(child:RightSidewidget()),
          Expanded(child:LeftSidewidget())
        ],

        )),

    );
  }
}

class RightSidewidget extends StatefulWidget {
  @override
  _RightSidewidgetState createState() => _RightSidewidgetState();
}
class _RightSidewidgetState extends State<RightSidewidget> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        child: Container(child:Text("add new ZzZ"),),
        **onTap: (){
          setState(() {
            ListOfZzZ.add("ZzZ");
          });},);**
  }
}

class LeftSidewidget extends StatefulWidget {
  @override
  _LeftSidewidgetState createState() => _LeftSidewidgetState();
}
class _LeftSidewidgetState extends State<LeftSidewidget> {
  @override
  Widget build(BuildContext context) {
    return Container(child:
      ListView.builder(
          itemCount: ListOfZzZ.length,
          itemBuilder: (context,index)=>Text(ListOfZzZ[index])),);
  }
}

2 Answers2

0

check the Provider package it can help you achieve what you want, ere is a really good tutorial by the flutter devs showing how to use manage the state of your app and notify widgets of the changes other widgets have.

Jaime Ortiz
  • 1,089
  • 10
  • 14
0

setState rebuild in very specyfic way. you can read about this in here: https://api.flutter.dev/flutter/widgets/State/setState.html

in simple world setState call the nearest build (I think this is not full true, but this intuitions works for me) In your code when you tap right widget and call setState only rightwidget will be rebuild.

So this is the easy solutions: Make left and right widget statless. In homescreen in row add gestureDetector(or textButton like in my example) and here call setState. When you do that, all homeSreen will be rebuild so left and right widget too. and your list will be actual. Here is example:

List<String> ListOfZzZ = [];

class homescreen extends StatefulWidget {
  @override
  _homescreenState createState() => _homescreenState();
}

class _homescreenState extends State<homescreen> {
  @override
  Widget build(BuildContext context) {
    return Material(
      child: Scaffold(
          body: Row(
        children: [
          Expanded(
              child: TextButton(
                  onPressed: () => setState(() {
                        ListOfZzZ.add("ZzZ");
                      }),
                  child: RightSidewidget())),
          Expanded(child: LeftSideWidget())
        ],
      )),
    );
  }
}

class RightSidewidget extends StatelessWidget {
  const RightSidewidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.amber[50],
      child: Text("add new ZzZ"),
    );
  }
}

class LeftSideWidget extends StatelessWidget {
  const LeftSideWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: ListView.builder(
          itemCount: ListOfZzZ.length,
          itemBuilder: (context, index) => Text(ListOfZzZ[index])),
    );
  }
}

The hard way, but more elegant and better is to use some state manager like bloc. Here is official site: https://bloclibrary.dev/#/gettingstarted there is a lot of tutorials and explanations. But this is not solutions for 5 minutes.

Edit: I make some solution with BLoC. I hope this help. I use flutter_bloc and equatable packages in version 7.0.1

void main() {
  EquatableConfig.stringify = kDebugMode;
  Bloc.observer = SimpleBlocObserver();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('myList'),
        ),
        body: BlocProvider(
          create: (context) => MylistBloc()..add(AddToList('Start')),
          child: Row(
            children: [
              Expanded(flex: 1, child: buttonsPanel()),
              Expanded(flex: 1, child: ListOfZzZ()),
            ],
          ),
        ),
      ),
    );
  }
}

class ListOfZzZ extends StatefulWidget {
  const ListOfZzZ({Key? key}) : super(key: key);

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

class _ListOfZzZState extends State<ListOfZzZ> {
  late MylistBloc _mylistBloc;

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<MylistBloc, MylistState>(
      //builder: (context, state) {return ListView.builder(itemBuilder: (BuildContext context,int index){return  ListTile(title: state.positions[index];)},);},
      builder: (context, state) {
        if (state.positions.isEmpty) {
          return const Center(child: Text('no posts'));
        } else {
          return ListView.builder(
            itemBuilder: (BuildContext context, int index) {
              return ListTile(title: Text(state.positions[index]));
            },
            itemCount: state.positions.length,
          );
        }
      },
    );
  }
}

class buttonsPanel extends StatefulWidget {
  const buttonsPanel({Key? key}) : super(key: key);

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

class _buttonsPanelState extends State<buttonsPanel> {
  late MylistBloc _mylistBloc;

  @override
  void initState() {
    super.initState();
    _mylistBloc = context.read<MylistBloc>();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        TextButton(
            onPressed: () => {_mylistBloc.add(AddToList('Spam'))},
            child: Text('Spam')),
        TextButton(
            onPressed: () => {_mylistBloc.add(AddToList('Ham'))},
            child: Text('Ham')),
      ],
    );
  }
class SimpleBlocObserver extends BlocObserver {
  @override
  void onTransition(Bloc bloc, Transition transition) {
    super.onTransition(bloc, transition);
    print(transition);
  }

  @override
  void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
    print(error);
    super.onError(bloc, error, stackTrace);
  }
}

class MylistState extends Equatable {
  final List<String> positions;
  final int lenght;
  const MylistState({this.positions = const <String>[], this.lenght = 0});

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

  @override
  String toString() => 'Lenght: {$lenght} Positions: {$positions}';

  @override
  MylistState copyWith(List<String>? positions) {
    return MylistState(positions: positions ?? this.positions);
  }
}


abstract class MylistEvent extends Equatable {
  const MylistEvent();

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

class AddToList extends MylistEvent {
  final String posToAdd;

  @override
  AddToList(this.posToAdd);
}


class MylistBloc extends Bloc<MylistEvent, MylistState> {
  MylistBloc() : super(MylistState(positions: const <String>[]));

  @override
  Stream<MylistState> mapEventToState(
    MylistEvent event,
  ) async* {
    if (event is AddToList) {
      yield await _mapListToState(state, event.posToAdd);
    }
  }

  Future<MylistState> _mapListToState(
      MylistState state, String posToAdd) async {
    List<String> positions = [];
    positions.addAll(state.positions);
    positions.add(posToAdd);

    return MylistState(positions: positions, lenght: positions.length);
  }
}

}

Corvus Albus
  • 156
  • 4