首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >对同一页面上的同一区块使用多个BlocConsumer

对同一页面上的同一区块使用多个BlocConsumer
EN

Stack Overflow用户
提问于 2021-05-25 04:55:32
回答 2查看 912关注 0票数 1

我在“MyButton”小部件中使用BlocConsumer,该小部件用于列表中的所有项目。当用户按下按钮时,我希望根据用户单击的按钮将用户重定向到另一个页面(在下面的代码中,打印的是按钮文本)。

如果我运行此代码,单击一个按钮将打印所有文本("Press 1“、"Press 2”、"Press 3")。是否因为完全相同的侦听器被附加到MyButton小部件3次,并且每次单击任何按钮时都会调用所有侦听器?这是否意味着同一页面上的区块不应该有多个小部件?

我可以通过移动BlocConsumer而不是MyButton来包装列来修复代码。这是处理这个问题的正确方法吗?如果是这样的话,我必须在更复杂的情况下包装一个更大的小部件。例如,如果appbar和body中的小部件使用相同的块,那么我将不得不用BlocConsumer包装整个页面。

代码语言:javascript
运行
复制
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

void main() async {
  runApp(BlocProvider<MyBloc>(
    create: (BuildContext context) => MyBloc(),
    child: MaterialApp(
      home: Column(
        children: [
          MyButton(text: "Press 1"),
          MyButton(text: "Press 2"),
          MyButton(text: "Press 3"),
        ],
      ),
    ),
  ));
}

class MyButton extends StatelessWidget {
  const MyButton({Key? key, required this.text}) : super(key: key);

  final String text;

  @override
  Widget build(BuildContext context) {
    return BlocConsumer<MyBloc, MyState>(
      listenWhen: (previous, current) {
        return true;
      },
      listener: (context, state) {
        print(text);
      },
      builder: (context, state) {
        return TextButton(
          key: UniqueKey(),
          child: Text(text),
          onPressed: () {
            context.read<MyBloc>().add(MyEvent());
          },
        );
      },
    );
  }
}

class MyEvent {}

class MyState {}

class MyBloc extends Bloc<MyEvent, MyState> {
  MyBloc() : super(MyState());

  @override
  Stream<MyState> mapEventToState(MyEvent event) async* {
    yield MyState();
  }
}
EN

回答 2

Stack Overflow用户

发布于 2021-05-25 12:34:33

要在bloc中处理不同的单击,您必须定义事件和状态。

代码语言:javascript
运行
复制
// events
class FirstClick extends Event{}

class SecondClick extends Event{}

class ThirdClick extends Event{}

// states
class FirstClickState extends State{}

class SecondClickState extends State{}

class ThirdClickState extends State{}

// bloc function 
class MyBloc extends Bloc<MyEvent, MyState> {
MyBloc() : super(MyState());

  @override
  Stream<MyState> mapEventToState(MyEvent event) async* {
    if(event is FirstClick){
      yield FirstClickState();
    }

    if(event is SecondClick){
      yield SecondClickState();
    }

    if(event is ThirdClick){
      yield ThirdClickState();
    }
  }  
}

// view definition
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

void main() async {
  runApp(BlocProvider<MyBloc>(
    create: (BuildContext context) => MyBloc(),
    child: MaterialApp(
    home: Column(
      children: [
        MyButton(text: "Press 1", onPressed:() => BlocProvider.of<MyBloc>(context).add(FirstClick())),
        MyButton(text: "Press 2", onPressed:() => BlocProvider.of<MyBloc>(context).add(SecondClick())),
        MyButton(text: "Press 3", onPressed:() => BlocProvider.of<MyBloc>(context).add(ThirdClick())),
        ],
      ),
    ),
  ));
}

class MyButton extends StatelessWidget {
const MyButton({Key? key, required this.text}) : super(key: key);

final String text;

@override
Widget build(BuildContext context) {
  return BlocConsumer<MyBloc, MyState>(
    listenWhen: (previous, current) {
      return true;
    },
    listener: (context, state) {
      if(state is FirstClickState){
        // go to where ever 
        Navigator.push(context, Somewhere());
      }
      
      if(state is SecondClickState){
        // go to where ever 
        Navigator.push(context, Somewhere());
      }

      if(state is ThirdClickState){
        // go to where ever 
        Navigator.push(context, Somewhere());
      }
    },
    builder: (context, state) {
      return TextButton(
        key: UniqueKey(),
        child: Text(text),
        onPressed: () {
          context.read<MyBloc>().add(MyEvent());
        },
      );
    },
  );
 }
}
票数 0
EN

Stack Overflow用户

发布于 2021-05-28 21:48:46

在页面数未定义的情况下,我使用状态类型为int的Cubit。这允许您拥有任意多的页面,并且页面的索引可以用作cubit的状态。

代码语言:javascript
运行
复制
class PagesCubit extends Cubit<int> {
  PagesCubit() : super(0);

  void selectPage(int index) => emit(index);

}

在你的代码中,你可以这样使用它。

代码语言:javascript
运行
复制
BlocProvider<PagesCubit>(
  lazy: false,
  create: (BuildContext context) => PagesCubit(),
  child: BlocListener<PagesCubit, int>(
    listener: (context, state) {
      print(state); // expects int value
      //TODO: navigate to page
    },
    child: MaterialApp(
    home: Column(
        children: [
          MyButton(text: "Press 1"),
          MyButton(text: "Press 2"),
          MyButton(text: "Press 3"),
        ],
      ),
    ),
  ),
)

//somewhere anywhere else in your code
context.read<PagesCubit>().selectPage(index);

注意:除非您知道要导航到的页面,否则不要处理按钮内部的导航。你最终会复制和粘贴大量的代码。相反,您可以将导航拉上一个级别(例如,围绕您的Column ),并在那里管理导航。之所以可以这样做,是因为bloc允许您将代码移动到它提供块的树中的任何位置。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67678870

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档