【问题标题】:How to setState widget by other widget Flutter ,simplecode below如何通过其他小部件 Flutter 设置状态小部件,下面的简单代码
【发布时间】:2021-08-26 22:16:04
【问题描述】:

右侧小部件具有将字符串 ("ZzZ") 添加到列表的 gesterdetector; 左侧小部件通过列表视图构建器在字符串列表中显示所有字符串,

按下按钮成功后,右侧小部件将“ZzZ”添加到列表中,但它会设置 ui 状态... 在热重载后在android studio中显示所有添加的“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])),);
  }
}

【问题讨论】:

    标签: flutter setstate state-management stateful statefulwidget


    【解决方案1】:

    setState 以非常具体的方式重建。你可以在这里阅读: https://api.flutter.dev/flutter/widgets/State/setState.html

    在简单的世界中 setState 调用最近的构建(我认为这并不完全正确,但这种直觉对我有用) 在您的代码中,当您点击右小部件并调用 setState 时,只会重建右小部件。

    所以这是简单的解决方案: 使左右小部件无状态。 在行中的主屏幕中添加gestureDetector(或我的示例中的textButton)并在此处调用setState。当你这样做时,所有 homeSreen 都将被重建,所以左右小部件也是如此。你的清单将是实际的。这是一个例子:

    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])),
        );
      }
    }
    

    使用一些像 bloc 这样的状态管理器是困难的,但更优雅和更好的方法。这里是官方网站:https://bloclibrary.dev/#/gettingstarted 有很多教程和解释。但这不是 5 分钟的解决方案。

    编辑:我用 BLoC 做了一些解决方案。我希望这会有所帮助。我在 7.0.1 版本中使用了 flutter_bloc 和 equatable 包

    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);
      }
    }
    

    }

    【讨论】:

    • 问题是这不是我的真实代码
    • CustomScrollView制作的真实代码( slivers: [ SliverFixedExtentList(
    • 所以当我想使用 didupdate 小部件时,它必须在新的有状态类中
    • 所以你应该使用 BLoC bloclibrary.dev/#/gettingstarted 或像 @JaimeOrtiz 提议的 ProviderPackage 之类的其他状态管理器。
    • @mohammadrezasalehi 我编辑我的回答并在 BLoC 中添加解决方案。我希望这可以帮助你。
    【解决方案2】:

    查看Provider package,它可以帮助您实现您想要的,这是由 Flutter 开发人员提供的 really good tutorial,展示了如何使用管理您的应用程序的状态并通知小部件其他小部件的更改。

    【讨论】:

      猜你喜欢
      • 2019-06-26
      • 1970-01-01
      • 1970-01-01
      • 2020-03-18
      • 2021-02-16
      • 2021-05-19
      • 2018-09-01
      • 2019-09-23
      • 2019-10-16
      相关资源
      最近更新 更多