You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Provider实现子组件操作后更新父级好友列表页面?

使用Provider实现子组件通知父组件刷新好友列表

核心思路是通过Provider的ChangeNotifier维护好友列表状态,子组件完成删除/拉黑操作后触发状态更新,父组件监听状态变化自动刷新列表,完全符合组件职责划分的直觉。

1. 创建好友状态管理类

新建一个继承ChangeNotifier的类,统一处理好友数据的加载、删除、拉黑逻辑,操作完成后调用notifyListeners()通知所有监听组件刷新。

import 'package:flutter/foundation.dart';
import '../services/database.dart';

class FriendListProvider extends ChangeNotifier {
  final Database _database = Database();
  List<Map<String, dynamic>> _friends = [];

  // 对外暴露只读的好友列表
  List<Map<String, dynamic>> get friends => _friends;

  // 从Firestore加载最新好友列表
  Future<void> loadFriends() async {
    _friends = await _database.getFriends(); // 假设你的Database类有该方法
    notifyListeners();
  }

  // 删除好友并刷新列表
  Future<void> removeFriend(String friendUID) async {
    await _database.removeFriend(friendUID);
    await loadFriends();
    notifyListeners();
  }

  // 拉黑好友并刷新列表
  Future<void> blockFriend(String friendUID) async {
    await _database.blockFriend(friendUID);
    await loadFriends();
    notifyListeners();
  }
}

2. 父组件集成Provider

在好友列表页面用ChangeNotifierProvider包裹,通过Consumer监听状态变化,自动重建好友列表。

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

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

  @override
  State<FriendListPage> createState() => _FriendListPageState();
}

class _FriendListPageState extends State<FriendListPage> {
  @override
  void initState() {
    super.initState();
    // 页面初始化时加载好友列表
    WidgetsBinding.instance.addPostFrameCallback((_) {
      Provider.of<FriendListProvider>(context, listen: false).loadFriends();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('好友列表')),
      body: Consumer<FriendListProvider>(
        builder: (context, provider, child) {
          if (provider.friends.isEmpty) {
            return const Center(child: Text('暂无好友'));
          }
          return ListView.builder(
            itemCount: provider.friends.length,
            itemBuilder: (context, index) {
              final friend = provider.friends[index];
              return FriendRow(
                friendUsername: friend['username'],
                friendUID: friend['uid'],
              );
            },
          );
        },
      ),
    );
  }
}

3. 修改FriendRow子组件

移除子组件内的数据库实例,改为通过Provider获取状态管理类,调用对应的操作方法,操作完成后自动触发父组件刷新。

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

enum MoreOptions { RemoveFriend, Block }

class FriendRow extends StatelessWidget {
  const FriendRow({
    Key? key,
    required this.friendUsername,
    required this.friendUID,
  }) : super(key: key);

  final String friendUsername;
  final String friendUID;

  Future _moreOptionsDialog(BuildContext context, MoreOptions selectedItem) {
    String dialogTitle = '';

    if (selectedItem == MoreOptions.RemoveFriend) {
      dialogTitle = '删除好友';
    }

    if (selectedItem == MoreOptions.Block) {
      dialogTitle = '拉黑好友';
    }

    final provider = Provider.of<FriendListProvider>(context, listen: false);

    return showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text(dialogTitle),
          actions: [
            TextButton(
              onPressed: () async {
                if (selectedItem == MoreOptions.RemoveFriend) {
                  await provider.removeFriend(friendUID);
                }
                if (selectedItem == MoreOptions.Block) {
                  await provider.blockFriend(friendUID);
                }
                Navigator.of(context).pop();
              },
              child: const Text('确认'),
            ),
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('取消'),
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
          flex: 2,
          child: Image.asset('assets/images/userPicture.png'),
        ),
        Expanded(
          flex: 8,
          child: Text(friendUsername),
        ),
        Expanded(
          flex: 1,
          child: PopupMenuButton<MoreOptions>(
            onSelected: (MoreOptions selectedItem) {
              _moreOptionsDialog(context, selectedItem);
            },
            itemBuilder: (BuildContext context) => <PopupMenuEntry<MoreOptions>>[
              const PopupMenuItem<MoreOptions>(
                value: MoreOptions.RemoveFriend,
                child: Text('删除好友'),
              ),
              const PopupMenuItem<MoreOptions>(
                value: MoreOptions.Block,
                child: Text('拉黑好友'),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

关键说明

  • 状态管理类统一处理数据逻辑,子组件仅负责UI渲染和触发操作,符合单一职责原则。
  • notifyListeners()会通知所有Consumer监听的组件重建,父组件的ListView自动加载最新好友列表。
  • 子组件中使用Provider.of<T>(context, listen: false)是因为仅需获取实例调用方法,无需监听状态变化。

内容的提问来源于stack exchange,提问作者whatwhatwhat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 19:45:09