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

Flutter Firebase他人主页显示自身关注列表问题求助

Flutter Firebase 关注列表展示问题修复方案

我用Flutter和Firebase开发应用,已经能正常显示自己的关注及粉丝列表,但进入他人个人主页后,点击“关注”按钮,页面显示的是我自己的关注列表,而不是该主页所有者的关注列表。需要修复这个问题,让点击他人主页的“关注”按钮时,展示该用户的关注对象列表。

数据库结构

数据库结构

现有代码

Follow_card代码

class FollowCard extends StatefulWidget {
  final snap;

  const FollowCard({
    Key? key,
    required this.snap,
  }) : super(key: key);

  @override
  State<FollowCard> createState() => _FollowCardState();
}

class _FollowCardState extends State<FollowCard> {
  List<dynamic> followList = []; // 建议不要用dynamic

  getdata() async {
    List<dynamic> followers = [];

    final currentUserSnapshot = await FirebaseFirestore.instance
        .collection('users')
        .doc(FirebaseAuth.instance.currentUser!.uid)
        .get();

    // 获取关注者ID列表
    List<String> followIds =
        List.from(currentUserSnapshot.data()!['following']);
    // 遍历ID获取对应的用户信息
    for (int i = 0; i < followIds.length; i++) {
      var followId = followIds[i];
      var data = await FirebaseFirestore.instance
          .collection('users')
          .doc(followId)
          .get();

      followers.add(data);
    }
    setState(() => followList = followers);
  }

  @override
  void initState() {
    super.initState();
    getdata();
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      physics: NeverScrollableScrollPhysics(),
      child: ListView.builder(
          shrinkWrap: true,
          itemCount: followList.length,
          itemBuilder: (context, index) {
            var followerItem = followList[index];
            print('photoUrl');

            return _buildFollowersCard(followerItem['photoUrl'],
                followerItem['username'], followerItem['uid']);
          }),
    );
  }

  Widget _buildFollowersCard(String photoUrl, String username, String uid) {
    return Container(
      height: 70,
      width: double.infinity,
      color: mobileBackgroundColor,
      child: Card(
        child: Column(children: [
          //Header
          Container(
            height: 40,
            width: double.infinity,
            padding: const EdgeInsets.symmetric(
              vertical: 4,
              horizontal: 16,
            ).copyWith(right: 0),
            child: Row(
              children: [
                CircleAvatar(
                  radius: 16,
                  backgroundImage: NetworkImage(
                    photoUrl,
                  ),
                ),
                Expanded(
                  child: Padding(
                    padding: EdgeInsets.only(left: 8),
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        TextButton(
                          onPressed: () {
                            Navigator.push(
                                context,
                                MaterialPageRoute(
                                    builder: (context) =>
                                        ProfileScreen(uid: uid)));
                          },
                          child: Text(
                            username,
                            style: TextStyle(
                                fontWeight: FontWeight.bold,
                                color: Colors.white),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          )
        ]),
      ),
    );
  }
}

Follow_screen代码

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

  @override
  State<FollowScreen> createState() => _FollowScreenState();
}

class _FollowScreenState extends State<FollowScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: mobileBackgroundColor,
        centerTitle: true,
        title: Image.asset(
          'Resim/logo.png',
          height: 50,
        ),
      ),
      body: StreamBuilder(
        stream: FirebaseFirestore.instance.collection('users').snapshots(),
        builder: (context,
            AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }
          return ListView.builder(
            itemCount: snapshot.data!.docs.length,
            itemBuilder: (context, index) => FollowCard(
              snap: snapshot.data!.docs[index].data(),
            ),
          );
        },
      ),
    );
  }
}

Profile_screen(按钮部分)代码

child: buildStatColumn(followers, 'Takipçi'),
                                    ),
                                    TextButton(
                                      onPressed: () {
                                        Navigator.push(
                                            context,
                                            MaterialPageRoute(
                                                builder: (context) =>
                                                    FollowScreen()));
                                      },

问题分析

  1. FollowCard硬编码当前用户:getdata方法里直接用FirebaseAuth.instance.currentUser!.uid获取当前用户数据,导致无论打开谁的主页,都只加载自己的关注列表。
  2. FollowScreen未接收目标用户ID:没有参数来指定要展示哪个用户的关注列表,无法传递主页所有者的ID。
  3. 跳转时未传递用户ID:ProfileScreen的按钮跳转FollowScreen时,没有把当前主页的用户ID传过去。

修复方案

1. 修改FollowScreen,添加用户ID参数

让FollowScreen接收要展示的用户UID,后续传递给FollowCard:

class FollowScreen extends StatefulWidget {
  final String targetUid; // 新增:目标用户ID

  const FollowScreen({Key? key, required this.targetUid}) : super(key: key);

  @override
  State<FollowScreen> createState() => _FollowScreenState();
}

class _FollowScreenState extends State<FollowScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: mobileBackgroundColor,
        centerTitle: true,
        title: Image.asset(
          'Resim/logo.png',
          height: 50,
        ),
      ),
      // 移除无用的StreamBuilder,直接传递targetUid给FollowCard
      body: FollowCard(targetUid: widget.targetUid),
    );
  }
}

2. 修改FollowCard,接收目标用户ID并加载对应数据

移除snap参数,改为接收targetUid,并根据这个ID加载关注列表:

class FollowCard extends StatefulWidget {
  final String targetUid; // 目标用户ID

  const FollowCard({
    Key? key,
    required this.targetUid,
  }) : super(key: key);

  @override
  State<FollowCard> createState() => _FollowCardState();
}

class _FollowCardState extends State<FollowCard> {
  List<DocumentSnapshot> followList = []; // 明确类型,不用dynamic

  getdata() async {
    List<DocumentSnapshot> followers = [];

    // 根据传入的targetUid获取目标用户数据
    final targetUserSnapshot = await FirebaseFirestore.instance
        .collection('users')
        .doc(widget.targetUid)
        .get();

    if (!targetUserSnapshot.exists || !targetUserSnapshot.data()!.containsKey('following')) {
      setState(() => followList = followers);
      return;
    }

    // 获取目标用户的关注ID列表
    List<String> followIds = List.from(targetUserSnapshot.data()!['following']);
    
    // 优化:用批量获取减少请求次数(比循环逐个请求更高效)
    if (followIds.isNotEmpty) {
      final followDocs = await FirebaseFirestore.instance
          .collection('users')
          .where(FieldPath.documentId, whereIn: followIds)
          .get();
      followers.addAll(followDocs.docs);
    }

    setState(() => followList = followers);
  }

  @override
  void initState() {
    super.initState();
    getdata();
  }

  @override
  Widget build(BuildContext context) {
    return followList.isEmpty 
        ? const Center(child: Text('暂无关注'))
        : ListView.builder(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            itemCount: followList.length,
            itemBuilder: (context, index) {
              var followerItem = followList[index].data() as Map<String, dynamic>;
              return _buildFollowersCard(
                followerItem['photoUrl'],
                followerItem['username'],
                followerItem['uid'],
              );
            },
          );
  }

  // _buildFollowersCard方法保持不变
  Widget _buildFollowersCard(String photoUrl, String username, String uid) {
    return Container(
      height: 70,
      width: double.infinity,
      color: mobileBackgroundColor,
      child: Card(
        child: Column(children: [
          Container(
            height: 40,
            width: double.infinity,
            padding: const EdgeInsets.symmetric(
              vertical: 4,
              horizontal: 16,
            ).copyWith(right: 0),
            child: Row(
              children: [
                CircleAvatar(
                  radius: 16,
                  backgroundImage: NetworkImage(photoUrl),
                ),
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.only(left: 8),
                    child: TextButton(
                      onPressed: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (context) => ProfileScreen(uid: uid),
                          ),
                        );
                      },
                      child: Text(
                        username,
                        style: const TextStyle(
                          fontWeight: FontWeight.bold,
                          color: Colors.white,
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          )
        ]),
      ),
    );
  }
}

3. 修改ProfileScreen的跳转逻辑,传递目标用户ID

在跳转FollowScreen时,把当前主页的用户UID传过去(假设widget.uid是当前主页的用户ID):

TextButton(
  onPressed: () {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => FollowScreen(targetUid: widget.uid),
      ),
    );
  },
  child: const Text('关注'),
),

额外优化建议

  • 避免在initState里直接发起异步请求,可使用FutureBuilder替代,减少状态管理复杂度
  • 给followList指定明确的类型(如List<DocumentSnapshot>),避免使用dynamic提升代码安全性
  • 批量获取用户数据时,注意Firebase的whereIn最多支持50个元素,超过的话需要拆分请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 00:24:30