提供者不重建颤振

Provider not rebuilding on flutter

我不知从哪里突然想到提供商在更新时不重新呈现我的主页。我已经检查过它并且它已更新。当我在 firebase 中更改它时它有更新的数据,但 UI 不会重新呈现以显示新数据。那是我的代码:

主要功能

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:my_event_app/pages/HomePage/home_page.dart';
import 'package:my_event_app/pages/Login/login_page.dart';
import 'package:my_event_app/providers/User/user.dart';
import 'package:provider/provider.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => UserModel()),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Flutter Demo',
        theme: ThemeData(
          // is not restarted.
          primarySwatch: Colors.blue,
        ),
        home: const Wrapper(),
      ),
    );
  }
}

class Wrapper extends StatelessWidget {
  const Wrapper({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.userChanges(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.active) {
          User? user = snapshot.data;
          if (user == null) {
            return const LoginPage();
          }
          return StreamBuilder<DocumentSnapshot>(
              stream: FirebaseFirestore.instance
                  .collection('users')
                  .doc(FirebaseAuth.instance.currentUser!.uid)
                  .snapshots(),
              builder: (context, userSnapshot) {
                if (userSnapshot.hasData) {
                  Provider.of<UserModel>(context, listen: true)
                      .fromJson(userSnapshot.data!.data());
                  return const HomePage();
                }
                return const Scaffold(
                  body: Center(
                    child: CircularProgressIndicator(),
                  ),
                );
              });
        } else {
          return const Scaffold(
            body: Center(
              child: CircularProgressIndicator(),
            ),
          );
        }
      },
    );
  }
}

这是主页:

import 'package:flutter/material.dart';
import 'package:my_event_app/http/auth/user/sign_out.dart';
import 'package:my_event_app/pages/Create_Event/create_event_page.dart';
import 'package:my_event_app/pages/Onboarding/onboarding_page.dart';
import 'package:my_event_app/providers/User/user.dart';
import 'package:my_event_app/widgets/event_card_widget.dart';
import 'package:provider/provider.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

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

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Consumer<UserModel>(builder: (context, user, child) {
      return Scaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: const Icon(Icons.help_outline, color: Colors.black, size: 30),
            onPressed: () {
              Navigator.push(context, MaterialPageRoute(builder: (context) {
                return const OnboardingPage();
              }));
            },
          ),
          actions: [
            IconButton(
              icon: const Icon(
                Icons.arrow_forward_ios_sharp,
                color: Colors.black,
              ),
              onPressed: () {
                signOut();
              },
            ),
          ],
          elevation: 0,
          backgroundColor: Colors.white,
        ),
        backgroundColor: Colors.white,
        body: SingleChildScrollView(
          child: Container(
            color: Colors.white,
            padding: const EdgeInsets.all(16),
            child: Column(
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    const CircleAvatar(
                      radius: 25,
                      backgroundImage: NetworkImage(
                          "https://cdnnmundo1.img.sputniknews.com/img/07e5/09/13/1116212032_100:0:1273:1173_1920x0_80_0_0_efb734331af13dfe11ff6d43293c60e2.png"),
                    ),
                    Container(
                      height: 50,
                      width: 50,
                      decoration: BoxDecoration(
                        color: Colors.orange[400],
                        borderRadius: BorderRadius.circular(10),
                        boxShadow: [
                          BoxShadow(
                            color: Colors.black.withOpacity(0.1),
                            spreadRadius: 1,
                            blurRadius: 5,
                            offset: const Offset(0, 3),
                          ),
                        ],
                      ),
                      child: Center(
                        child: IconButton(
                          color: Colors.white,
                          onPressed: () {
                            // Navigate to add event widget
                            Navigator.push(context,
                                MaterialPageRoute(builder: (context) {
                              return const CreateEventPage();
                            }));
                          },
                          icon: const Icon(Icons.add),
                        ),
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 32),
                SizedBox(
                  width: double.infinity,
                  child: Text('Welcome, ${user.name}',
                      style: const TextStyle(
                          fontSize: 28,
                          fontWeight: FontWeight.bold,
                          fontFamily: "Roboto")),
                ),
                const SizedBox(height: 32),
                Container(
                  padding: const EdgeInsets.all(16),
                  height: 100,
                  width: double.infinity,
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(10),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.black.withOpacity(0.1),
                        spreadRadius: 1,
                        blurRadius: 5,
                        offset: const Offset(0, 3),
                      ),
                    ],
                  ),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Stack(alignment: Alignment.center, children: [
                        SizedBox(
                          height: 45,
                          width: 45,
                          child: CircularProgressIndicator(
                            valueColor:
                                AlwaysStoppedAnimation(Colors.orange[400]),
                            value: 14 / 20,
                            semanticsValue: "14/20",
                            color: Colors.black,
                          ),
                        ),
                        const Text("78%",
                            style: TextStyle(
                                fontSize: 14,
                                fontWeight: FontWeight.bold,
                                fontFamily: "Roboto")),
                      ]),
                      Column(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: const [
                          Text("Weekly progress",
                              style: TextStyle(
                                fontSize: 14,
                                fontWeight: FontWeight.w600,
                              )),
                          Text("14/20 tasks completed"),
                        ],
                      ),
                      const Icon(Icons.bar_chart),
                    ],
                  ),
                ),
                Container(
                  margin: const EdgeInsets.symmetric(vertical: 16),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: const [
                      Text("You have 5 tasks for today",
                          style: TextStyle(
                            fontSize: 14,
                            fontWeight: FontWeight.w600,
                          )),
                      Icon(Icons.calendar_today_outlined)
                    ],
                  ),
                ),
                _renderEvents(user),
              ],
            ),
          ),
        ),
      );
    });
  }
}

Column _renderEvents(UserModel user) {
  return Column(
    children: [
      for (var event in user.events)
        EventCard(
          eventId: event,
        ),
    ],
  );
}

这是提供商:

import 'package:flutter/material.dart';

class UserModel extends ChangeNotifier {
  String _name = '';
  String _surnames = '';
  String _uid = '';
  String _email = '';
  List<dynamic> _events = [];

  String get name => _name;
  String get surnames => _surnames;
  String get uid => _uid;
  String get email => _email;
  List<dynamic> get events => _events;

  UserModel();

  set name(String value) {
    _name = value;
    notifyListeners();
  }

  set surnames(String value) {
    _surnames = value;
    notifyListeners();
  }

  set uid(String value) {
    _uid = value;
    notifyListeners();
  }

  set email(String value) {
    _email = value;
    notifyListeners();
  }

  set events(List<dynamic> value) {
    _events = value;
    notifyListeners();
  }

  void addEvent(String event) {
    _events.add(event);
    notifyListeners();
  }

  void removeEvent(String event) {
    _events.remove(event);
    notifyListeners();
  }

  void updateUser(String name, String uid) {
    name = name;
    uid = uid;
    notifyListeners();
  }

  void clearUser() {
    _name = '';
    _uid = '';
    notifyListeners();
  }

  Map<String, dynamic> toJson() {
    return {
      'name': _name,
      'surnames': _surnames,
      'uid': _uid,
      'email': _email,
      'events': _events
    };
  }

  fromJson(Object? json) {
    try {
      Map<dynamic, dynamic> map = json as Map<dynamic, dynamic>;
      _name = map['name'];
      _surnames = map['surnames'];
      _uid = map['uid'];
      _email = map['email'];
      _events = map['events'];
    } catch (e) {
      print(e);
    }
  }
}
```
As you can see i use Consumer in order to read data and i have a change notifier in the begginig, but it won't re render and show for example new name if i change it in fireabase.

Thank you so much!

您正在使用 fromJson 方法更新 UserModel 中的值,但它没有调用 notifyListeners。在该方法末尾添加notifyListeners();

fromJson(Object? json) {
    try {
      Map<dynamic, dynamic> map = json as Map<dynamic, dynamic>;
      _name = map['name'];
      _surnames = map['surnames'];
      _uid = map['uid'];
      _email = map['email'];
      _events = map['events'];
      notifyListeners(); // add this
    } catch (e) {
      print(e);
    }
  }

还有一些其他的东西:

  • 考虑声明 class UserModel with ChangeNotifier 而不是 class UserModel extends ChangeNotifier
  • fromJson 方法通常充当工厂方法,这意味着这些 return 一个新实例,并且不在现有实例中设置成员。
  • 您可以尝试 context.read<UserModel>().fromJson(userSnapshot.data!.data()); 而不是 Provider.of<UserModel>(context, listen: true).fromJson(userSnapshot.data!.data());。在这里你真的不需要监听,你只是想找到提供者并调用fromJson。您的 Consumer 正在相应地监听更改。