Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
622 views
in Technique[技术] by (71.8m points)

widget - Flutter Provider listen to class that extends ChangeNotifier later when created

I use the flutter Provider package to kind of create a observable state behaviour for classes that extend ChangeNotifier..

I have a Person class that extends StatelessWidget so I could create a Person widget.

I first create an instance of Person class one time in the builder method of

ChangeNotifierProvider<Person>(
    builder: (context) => Person(name: 'Jim', age: 1),
),

and another time later, deeper down the widget tree as a child, but that other Person naturally has no listener...

so I tried to wrap my second Person inside another ChangeNotifierProvider down in the tree, but then I got this error:

======== Exception caught by widgets library =======================================================
The following assertion was thrown building InheritedProvider<Person>(dirty):
A build function returned null.

The offending widget is: InheritedProvider<Person>
Build functions must never return null.

Maybe the problem is, that I have 2 ChangeNotifierProviders with the same type (one named "Jim" at the top and one in Level 2 class named "Bob") and it does not know which is which and how to update their state? Is it kind of possible to create 2 classes of same ChangeNotifierProviders type just named differently or so? Here is the full code:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<Data>(
          builder: (context) => Data(),
        ),
        ChangeNotifierProvider<Person>(
          builder: (context) => Person(name: 'Jim', age: 1),
        ),
      ],
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: MyText(),
          ),
          body: Level1(),
        ),
      ),
    );
  }
}

class Person extends StatelessWidget with ChangeNotifier {
  String name;
  int age;
  Person({this.name, this.age});

  void increaseAge() {
    print(age);
    this.age++;
    notifyListeners();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text(
        'My name is $name and my age is: ${age.toString()}',
      ),
    );
  }
}

class Level1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Level2(),
        FlatButton(
          onPressed: () {
            print(Provider.of<Person>(context).age);
            Provider.of<Person>(context).increaseAge();
          },
          child: Text('Increase person age!'),
        ),
        Text(
            'My name is ${Provider.of<Person>(context).name} and my age is ${Provider.of<Person>(context).age}'),
      ],
    );
  }
}

class Level2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        MyTextField(),
        Level3(),
        ChangeNotifierProvider<Person>(
          builder: (context) => Person(
            name: 'Bob',
            age: 33,
          ),
        ),
      ],
    );
  }
}

class Level3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text(Provider.of<Data>(context).data);
  }
}

class MyText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text(Provider.of<Data>(context, listen: false).data);
  }
}

class MyTextField extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return TextField(
      onChanged: (newText) {
        Provider.of<Data>(context).changeString(newText);
      },
    );
  }
}

class Data extends ChangeNotifier {
  String data = 'Some data';

  void changeString(String newString) {
    data = newString;
    notifyListeners();
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...