Flutter 让机架在洗牌后更新

Flutter 让机架在洗牌后更新,flutter,Flutter,在下面的示例中,在洗牌之后,要更新机架,最好使用什么构造 在我看来,当创建一个StatefulWidget及其相应的State对象(SO)时,您可以从别处调用的任何方法都是附加到widget本身(而不是SO)的方法 但是,为了让小部件更新其显示,SetState()方法只能放在SO的方法中。那么小部件上的方法如何调用其So上的方法呢 import 'package:flutter/material.dart'; List<Block> g_blocks = [Block(Color

在下面的示例中,在洗牌之后,要更新机架,最好使用什么构造

在我看来,当创建一个StatefulWidget及其相应的State对象(SO)时,您可以从别处调用的任何方法都是附加到widget本身(而不是SO)的方法

但是,为了让小部件更新其显示,SetState()方法只能放在SO的方法中。那么小部件上的方法如何调用其So上的方法呢

import 'package:flutter/material.dart';

List<Block> g_blocks = [Block(Colors.red), Block(Colors.green), Block(Colors.blue)];
Rack g_rack = new Rack();

void main() => runApp(MyApp());

// This widget is the root of your application.
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        fontFamily: 'PressStart',
      ),
      home: MyHomeScreen(),
    );
  }
}

class MyHomeScreen extends StatefulWidget {
  MyHomeScreen({Key key}) : super(key: key);
  createState() => MyHomeScreenState();
}

class MyHomeScreenState extends State<MyHomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Center(child: Text('Thanks for your help')),
        backgroundColor: Colors.pink,
      ),
      body: Center(
        child: g_rack,
      ),
      bottomNavigationBar: SizedBox(
        height: 100.0,
        child: BottomNavigationBar(
          currentIndex: 0,
          iconSize: 48.0,
          backgroundColor: Colors.lightBlue[100],
          items: [
            BottomNavigationBarItem(
              label: 'Shuffle',
              icon: Icon(Icons.home),
            ),
            BottomNavigationBarItem(
              label: 'Shuffle',
              icon: Icon(Icons.home),
            ),
          ],
          onTap: (int indexOfItem) {
            setState(() {
              g_blocks.shuffle;
              rack.updateScreen();  // ** How to get the rack to update? **
            });
          },
        ),
      ),
    );
  }   // build
}   // End class MyHomeScreenState

class Rack extends StatefulWidget {
  @override
  _rackState createState() => _rackState();
}

class _rackState extends State<Rack> {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 150.0,
      color: Colors.yellow[200],
      child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          // mainAxisAlignment: MainAxisAlignment.spaceBetween,
          mainAxisSize: MainAxisSize.max,
          children: g_blocks),
    );
  }
  void updateRack(){
    setState(() {
      g_blocks.shuffle;
    });
  }
}

class Block extends StatelessWidget {
  final Color color;
  Block(this.color);
  @override
  Widget build(BuildContext context) {
    return Container(height:50,width:50, color: color,);
  }
}
导入“包装:颤振/材料.省道”;
列出g_块=[Block(Colors.red)、Block(Colors.green)、Block(Colors.blue)];
机架g_机架=新机架();
void main()=>runApp(MyApp());
//此小部件是应用程序的根。
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
主题:主题数据(
fontFamily:'按开始',
),
主页:MyHomeScreen(),
);
}
}
类MyHomeScreen扩展StatefulWidget{
MyHomeScreen({Key}):超级(Key:Key);
createState()=>MyHomeScreenState();
}
类MyHomeScreenState扩展了状态{
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:中心(儿童:文本(“感谢您的帮助”),
背景颜色:Colors.pink,
),
正文:中(
孩子:g_rack,
),
底部导航栏:大小框(
高度:100.0,
子项:底部导航栏(
当前索引:0,
iconSize:48.0,
背景颜色:颜色。浅蓝色[100],
项目:[
底部导航气压计(
标签:'Shuffle',
图标:图标(Icons.home),
),
底部导航气压计(
标签:'Shuffle',
图标:图标(Icons.home),
),
],
onTap:(int indexOfItem){
设置状态(){
g_blocks.shuffle;
rack.updateScreen();//**如何获取要更新的机架**
});
},
),
),
);
}//构建
}//结束类MyHomeScreenState
类Rack扩展StatefulWidget{
@凌驾
_rackState createState()=>rackState();
}
类_rackState扩展了状态{
@凌驾
小部件构建(构建上下文){
返回容器(
高度:150.0,
颜色:颜色。黄色[200],
孩子:排(
mainAxisAlignment:mainAxisAlignment.space,
//mainAxisAlignment:mainAxisAlignment.spaceBetween,
mainAxisSize:mainAxisSize.max,
儿童:g_街区),
);
}
void updateRack(){
设置状态(){
g_blocks.shuffle;
});
}
}
类块扩展了无状态小部件{
最终颜色;
块(此颜色);
@凌驾
小部件构建(构建上下文){
返回容器(高度:50,宽度:50,颜色:颜色,);
}
}

这里是一个解决方案,我尝试将应用程序的状态管理和业务逻辑与用户界面分离

我使用了以下软件包:

  • 对于域实体
  • 为国家管理

1.域层:实体 我们需要两个实体来为
块的
机架
建模

  • 由其
    颜色定义
  • 没有业务逻辑
  • 机架
    块的有序列表
  • 机架
    可以进行
    洗牌
  • 机架可以为(随机或给定)数量的
    块随机创建
3.表示层:用户界面 用户界面由四个小部件组成:

  • AppWidget
    [无状态widget]
  • 主页
    [HookWidget]
  • RackWidget
    [无状态Widget]
  • BlockWidget
    [无状态widget]
如您所见,真正关心应用程序状态的唯一小部件是
主页

3.1 AppWidget 3.2网页
机架
由我们的StateNotifierProvider在监视模式下提供:

final rack = useProvider(RackStateNotifier.provider.state);
机架
在读取模式下使用相同的提供程序进行处理和洗牌:

...
context.read(RackStateNotifier.provider).deal(),
...
context.read(RackStateNotifier.provider).shuffle(),
...
3.3 RackWidget 基本无状态小部件。我们使用LayoutBuilder来定义
块widgets
的大小

3.4区块小部件 另一个基本的无状态小部件


完整应用程序代码 只需复制粘贴以下内容即可尝试

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

part '66053795.shuffle.freezed.dart';

Random random = Random();

void main() => runApp(ProviderScope(child: AppWidget()));

class AppWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: Colors.amber,
        accentColor: Colors.black87,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final rack = useProvider(RackStateNotifier.provider.state);
    return Scaffold(
      appBar: AppBar(
        title: Row(
          children: const [
            Icon(Icons.casino_outlined),
            SizedBox(
              width: 8.0,
            ),
            Text('Rack Shuffler'),
          ],
        ),
      ),
      body: Center(
        child: RackWidget(rack: rack),
      ),
      bottomNavigationBar: BottomAppBar(
        color: Theme.of(context).primaryColor,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            IconButton(
              icon: Icon(Icons.refresh),
              iconSize: 48,
              onPressed: () => context.read(RackStateNotifier.provider).deal(),
            ),
            IconButton(
              icon: Icon(Icons.shuffle),
              iconSize: 48,
              onPressed: () =>
                  context.read(RackStateNotifier.provider).shuffle(),
            ),
          ],
        ),
      ),
    );
  }
}

class RackWidget extends StatelessWidget {
  final Rack rack;

  const RackWidget({Key key, this.rack}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: LayoutBuilder(
        builder: (context, constraints) {
          return Row(
            children: rack.blocks
                .map((block) => BlockWidget(
                    block: block,
                    size: constraints.biggest.width / rack.blocks.length))
                .toList(),
          );
        },
      ),
    );
  }
}

class BlockWidget extends StatelessWidget {
  final Block block;
  final double size;

  const BlockWidget({
    Key key,
    this.block,
    this.size,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: size,
      height: size,
      child: Padding(
        padding: EdgeInsets.all(size / 10),
        child: Container(
          decoration: BoxDecoration(
            color: block.color,
            border: Border.all(color: Colors.black87, width: size / 20),
            borderRadius: BorderRadius.circular(size / 15),
          ),
        ),
      ),
    );
  }
}

class RackStateNotifier extends StateNotifier<Rack> {
  static final provider =
      StateNotifierProvider<RackStateNotifier>((ref) => RackStateNotifier());

  RackStateNotifier([Rack state]) : super(state ?? Rack.create());

  void shuffle() {
    state = state.shuffled;
  }

  void deal() {
    state = Rack.create();
  }
}

@freezed
abstract class Block with _$Block {
  const factory Block({Color color}) = _Block;
}

@freezed
abstract class Rack implements _$Rack {
  const factory Rack({List<Block> blocks}) = _Rack;
  const Rack._();

  static Rack create([int nbBlocks]) => Rack(
        blocks: List.generate(
          nbBlocks ?? 4 + random.nextInt(6),
          (index) => Block(
            color: Color(0x66000000 + random.nextInt(0xffffff)),
          ),
        ),
      );

  Rack get shuffled => Rack(blocks: blocks..shuffle());
}
import'dart:math';
进口“包装:颤振/材料.省道”;
进口“包装:颤振钩/颤振钩.省道”;
导入“package:freezed_annotation/freezed_annotation.dart”;
进口“包装:hooks_riverpod/hooks_riverpod.dart”;
第66053795部分:洗牌,冷冻,飞镖;
随机=随机();
void main()=>runApp(ProviderScope(子:AppWidget());
类AppWidget扩展了无状态Widget{
@凌驾
小部件构建(构建上下文){
返回材料PP(
debugShowCheckedModeBanner:false,
主题:主题数据(
primaryColor:Colors.琥珀色,
accentColor:Colors.black87,
),
主页:主页(),
);
}
}
类主页扩展了小部件{
@凌驾
小部件构建(构建上下文){
最终机架=useProvider(RackStateNotifier.provider.state);
返回脚手架(
appBar:appBar(
标题:世界其他地区(
儿童:康斯特[
图标(图标。赌场),
大小盒子(
宽度:8.0,
),
文本('Rack Shuffler'),
],
),
),
正文:中(
子:机架小部件(机架:机架),
),
bottomNavigationBar:BottomAppBar(
颜色:主题。背景。原色,
孩子:排(
mainAxisAlignment:mainAxisAlignment.spaceAround,
儿童:[
图标按钮(
图标:图标(Icons.refresh),
iconSize:48,
onPressed:()=>context.rea
class HomePage extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final rack = useProvider(RackStateNotifier.provider.state);
    return Scaffold(
      appBar: AppBar(
        title: Row(
          children: const [
            Icon(Icons.casino_outlined),
            SizedBox(
              width: 8.0,
            ),
            Text('Rack Shuffler'),
          ],
        ),
      ),
      body: Center(
        child: RackWidget(rack: rack),
      ),
      bottomNavigationBar: BottomAppBar(
        color: Theme.of(context).primaryColor,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            IconButton(
              icon: Icon(Icons.refresh),
              iconSize: 48,
              onPressed: () => context.read(RackStateNotifier.provider).deal(),
            ),
            IconButton(
              icon: Icon(Icons.shuffle),
              iconSize: 48,
              onPressed: () =>
                  context.read(RackStateNotifier.provider).shuffle(),
            ),
          ],
        ),
      ),
    );
  }
}
final rack = useProvider(RackStateNotifier.provider.state);
...
context.read(RackStateNotifier.provider).deal(),
...
context.read(RackStateNotifier.provider).shuffle(),
...
class RackWidget extends StatelessWidget {
  final Rack rack;

  const RackWidget({Key key, this.rack}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: LayoutBuilder(
        builder: (context, constraints) {
          return Row(
            children: rack.blocks
                .map((block) => BlockWidget(
                    block: block,
                    size: constraints.biggest.width / rack.blocks.length))
                .toList(),
          );
        },
      ),
    );
  }
}
class BlockWidget extends StatelessWidget {
  final Block block;
  final double size;

  const BlockWidget({
    Key key,
    this.block,
    this.size,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: size,
      height: size,
      child: Padding(
        padding: EdgeInsets.all(size / 10),
        child: Container(
          decoration: BoxDecoration(
            color: block.color,
            border: Border.all(color: Colors.black87, width: size / 20),
            borderRadius: BorderRadius.circular(size / 15),
          ),
        ),
      ),
    );
  }
}
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

part '66053795.shuffle.freezed.dart';

Random random = Random();

void main() => runApp(ProviderScope(child: AppWidget()));

class AppWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: Colors.amber,
        accentColor: Colors.black87,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final rack = useProvider(RackStateNotifier.provider.state);
    return Scaffold(
      appBar: AppBar(
        title: Row(
          children: const [
            Icon(Icons.casino_outlined),
            SizedBox(
              width: 8.0,
            ),
            Text('Rack Shuffler'),
          ],
        ),
      ),
      body: Center(
        child: RackWidget(rack: rack),
      ),
      bottomNavigationBar: BottomAppBar(
        color: Theme.of(context).primaryColor,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            IconButton(
              icon: Icon(Icons.refresh),
              iconSize: 48,
              onPressed: () => context.read(RackStateNotifier.provider).deal(),
            ),
            IconButton(
              icon: Icon(Icons.shuffle),
              iconSize: 48,
              onPressed: () =>
                  context.read(RackStateNotifier.provider).shuffle(),
            ),
          ],
        ),
      ),
    );
  }
}

class RackWidget extends StatelessWidget {
  final Rack rack;

  const RackWidget({Key key, this.rack}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: LayoutBuilder(
        builder: (context, constraints) {
          return Row(
            children: rack.blocks
                .map((block) => BlockWidget(
                    block: block,
                    size: constraints.biggest.width / rack.blocks.length))
                .toList(),
          );
        },
      ),
    );
  }
}

class BlockWidget extends StatelessWidget {
  final Block block;
  final double size;

  const BlockWidget({
    Key key,
    this.block,
    this.size,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: size,
      height: size,
      child: Padding(
        padding: EdgeInsets.all(size / 10),
        child: Container(
          decoration: BoxDecoration(
            color: block.color,
            border: Border.all(color: Colors.black87, width: size / 20),
            borderRadius: BorderRadius.circular(size / 15),
          ),
        ),
      ),
    );
  }
}

class RackStateNotifier extends StateNotifier<Rack> {
  static final provider =
      StateNotifierProvider<RackStateNotifier>((ref) => RackStateNotifier());

  RackStateNotifier([Rack state]) : super(state ?? Rack.create());

  void shuffle() {
    state = state.shuffled;
  }

  void deal() {
    state = Rack.create();
  }
}

@freezed
abstract class Block with _$Block {
  const factory Block({Color color}) = _Block;
}

@freezed
abstract class Rack implements _$Rack {
  const factory Rack({List<Block> blocks}) = _Rack;
  const Rack._();

  static Rack create([int nbBlocks]) => Rack(
        blocks: List.generate(
          nbBlocks ?? 4 + random.nextInt(6),
          (index) => Block(
            color: Color(0x66000000 + random.nextInt(0xffffff)),
          ),
        ),
      );

  Rack get shuffled => Rack(blocks: blocks..shuffle());
}
import 'package:flutter/material.dart';

List<Block> g_blocks = [Block(Colors.red), Block(Colors.green),
  Block(Colors.blue), Block(Colors.purple)];
GlobalKey g_key = GlobalKey();
Rack g_rack = new Rack(key: g_key);

void main() => runApp(MyApp());

// This widget is the root of your application.
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        fontFamily: 'PressStart',
      ),
      home: MyHomeScreen(),
    );
  }
}

class MyHomeScreen extends StatefulWidget {
  MyHomeScreen({Key key}) : super(key: key);
  createState() => MyHomeScreenState();
}

class MyHomeScreenState extends State<MyHomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Center(child: Text('Thanks for your help')),
        backgroundColor: Colors.pink,
      ),
      body: Center(
        child: g_rack,
      ),
      bottomNavigationBar: SizedBox(
        height: 100.0,
        child: BottomNavigationBar(
          currentIndex: 0,
          iconSize: 48.0,
          backgroundColor: Colors.lightBlue[100],
          items: [
            BottomNavigationBarItem(
              label: 'Shuffle',
              icon: Icon(Icons.home),
            ),
            BottomNavigationBarItem(
              label: 'Shuffle',
              icon: Icon(Icons.home),
            ),
          ],
          onTap: (int index) {
            g_blocks.shuffle();
            g_key.currentState.setState(() {
            });
          }
        ),
      ),
    );
  }   // build
}   // End class MyHomeScreenState

class Rack extends StatefulWidget {
  Rack({Key key}) : super(key: key);
  @override
  _rackState createState() => _rackState();
}

class _rackState extends State<Rack> {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 150.0,
      color: Colors.yellow[200],
      child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          mainAxisSize: MainAxisSize.max,
          children: g_blocks),
    );
  }
  void updateRack(){
    setState(() {});
  }
}

class Block extends StatelessWidget {
  final Color color;
  Block(this.color);
  @override
  Widget build(BuildContext context) {
    return Container(height:50,width:50, color: color,);
  }
}