简体   繁体   English

Flutter Provider.of<> 没有消费者不要更改我的 state

[英]Flutter Provider.of<> without a consumer don't change my state

I am trying to get into the provider topic, however calling a function only works if I put it into a consumer我正在尝试进入提供者主题,但是调用 function 仅在我将其放入消费者时才有效

@override
Widget build(BuildContext context) {
return MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (_) => ClickerProvider()),
    ],
    child: Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Text("some text"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => Provider.of<ClickerProvider>(context, listen: false)
                          .incrementCounter(),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    ));
}

As in this example, my state is not updated.如本例所示,我的 state 未更新。 However, it already works with a consumer.但是,它已经与消费者合作。

floatingActionButton: Consumer<ClickerProvider>(
builder: (context, value, child) {
  return FloatingActionButton(
    onPressed: Provider.of<ClickerProvider>(context, listen: false)
        .incrementCounter,
    tooltip: 'Increment',
    child: Icon(Icons.add),
  );
},
)

Is there an error in my code?我的代码有错误吗?

As you can refer in the source code of Consumer here:您可以在此处参考Consumer源代码

Obtains [Provider] from its ancestors and passes its value to [builder].从其祖先获取 [Provider] 并将其值传递给 [builder]。

The [Consumer] widget doesn't do any fancy work. [Consumer] 小部件不做任何花哨的工作。 It just calls [Provider.of] in a new widget, and delegates its build implementation to [builder].它只是在一个新的小部件中调用 [Provider.of],并将其build实现委托给 [builder]。

Provider.of<X> depends on value of listen ( true or false ) to trigger new State.build() to widgets and State.didChangeDependencies() for StatefulWidget . Provider.of<X>取决于 listen 的值( truefalse )来触发新的State.build()到小部件和State.didChangeDependencies()StatefulWidget

Consumer<X> always update UI, as it uses Provider.of<T>(context) , where listen is true Consumer<X>总是更新 UI,因为它使用Provider.of<T>(context) ,其中 listen 为true

In this case, since your listen is set as false, but you're putting it in the Consumer which make it true .在这种情况下,由于您的listen设置为 false ,但您将其放入Consumer使其变为true That's why the UI will update with Consumer这就是 UI 将使用Consumer更新的原因

You can copy paste run two full code below您可以在下面复制粘贴运行两个完整代码
Reason: Can not find ClickerProvider原因:找不到ClickerProvider
Solution 1: Move ClickerProvider to upper level such as MyApp解决方案一:将ClickerProvider移到MyApp等上层

class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MultiProvider(
            providers: [
              ChangeNotifierProvider(create: (_) => ClickerProvider()),
            ],
            child: MaterialApp(

Solution 2: Use Builder解决方案 2:使用Builder

body: Center(child: Builder(builder: (BuildContext context) {
                return Text(context.watch<ClickerProvider>().getCounter.toString());
              })),
floatingActionButton: Builder(builder: (BuildContext context) {
    return FloatingActionButton(
      onPressed: () =>
          Provider.of<ClickerProvider>(context, listen: false)
              .incrementCounter(),
      tooltip: 'Increment',
      child: Icon(Icons.add),
    );

full code 1完整代码 1

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class ClickerProvider extends ChangeNotifier {
  int _count = 0;

  int get getCounter {
    return _count;
  }

  void incrementCounter() {
    _count += 1;
    notifyListeners();
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider(create: (_) => ClickerProvider()),
        ],
        child: MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        ));
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(
          child: Text(context.watch<ClickerProvider>().getCounter.toString()),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () => Provider.of<ClickerProvider>(context, listen: false)
              .incrementCounter(),
          tooltip: 'Increment',
          child: Icon(Icons.add),
        ));
  }
}

full code 2完整代码 2

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class ClickerProvider extends ChangeNotifier {
  int _count = 0;

  int get getCounter {
    return _count;
  }

  void incrementCounter() {
    _count += 1;
    notifyListeners();
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider(create: (_) => ClickerProvider()),
        ],
        child: Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(child: Builder(builder: (BuildContext context) {
            return Text(context.watch<ClickerProvider>().getCounter.toString());
          })),
          floatingActionButton: Builder(builder: (BuildContext context) {
            return FloatingActionButton(
              onPressed: () =>
                  Provider.of<ClickerProvider>(context, listen: false)
                      .incrementCounter(),
              tooltip: 'Increment',
              child: Icon(Icons.add),
            );
          }),
        ));
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM