首页 > 解决方案 > Flutter - 如何正确创建一个内部有微调器的按钮小部件以隔离 setState 调用?

问题描述

我有一个可重用的有状态小部件,它返回一个按钮布局。当网络调用正在进行时,按钮文本变为加载微调器,并在网络请求完成时变为文本。

我可以showSpinner从小部件外部传递一个参数,但这需要在小部件外部调用 setState,这会导致其他小部件的重建。

所以我需要从按钮小部件内部调用 setState 。

我还将回调作为参数传递给按钮小部件。有没有办法将微调器更改状态设置隔离到这样的小部件内部,以便它仍然可以重用?

标签: flutterflutter-layout

解决方案


你可以用它StreamBuilder来解决这个问题。

首先,我们需要创建一个stream. 创建一个新文件来存储它,我们将其命名banana_stream.dart,例如;)。

class BananaStream{
  final _streamController = StreamController<bool>();
  Stream<bool> get stream => _streamController.stream;
  
  void dispose(){
    _streamController.close();
  }
  
  void add(bool isLoading){
    _streamController.sink.add(isLoading);
  }
}

要访问它,您应该使用Provider, 因此添加一个Provider作为Widget包含可重用按钮的父级。

Provider<BananaStream>(
create: (context) => BananaStream(),
dispose: (context, bloc) => bloc.dispose(),
child: YourWidget(), 
),

然后添加StreamBuilder到您的按钮小部件:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<bool>(
    stream: Provider.of<BananaStream>(context, listen:false),
    initialData: false,
    builder: (context, snapshot){
    final isLoading = snapshot.data;
    if(isLoading == false){
    return YourButtonWithNoSpinner();
    } else{
    return YourButtonWithSpinner();
    }
    }
    );
  }
}

要更改 isLoading 外部,您可以使用以下代码:

final provider = Provider.of<BananaStream>(context, listen:false);
provider.add(true); //here is where you change the isLoading value

而已!

或者,您可以使用ValueNotifierorChangeNotifier但我发现它很难实现。


推荐阅读