# FollowFansActivity 关注/粉丝列表页面逻辑分析 ## 📋 概述 `FollowFansActivity` 是一个用于展示用户关注列表或粉丝列表的页面,支持下拉刷新和上拉加载更多功能。通过 `mType` 参数区分显示关注列表还是粉丝列表。 --- ## 🎯 核心功能 1. **列表展示**:显示关注列表或粉丝列表 2. **分页加载**:支持分页加载更多数据 3. **下拉刷新**:支持下拉刷新列表 4. **上拉加载**:支持上拉加载更多 5. **关注操作**:在粉丝列表中可以直接关注未关注的用户 6. **用户详情**:点击头像查看用户详细信息 --- ## 📊 页面类型(mType) ### 类型定义 ```java // 类型1=粉丝列表 2=关注列表 3=点赞列表(目前未使用) ``` ### 页面标题 - **mType = "1"**:显示"我的粉丝" - **mType = "2"**:显示"我的关注" ### 跳转入口 ```java // MeFragment.java 中跳转 // 关注列表 view.findViewById(R.id.ln_follow).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(getActivity(), FollowFansActivity.class); intent.putExtra("mType", "2"); // 2=关注列表 intent.putExtra("user_id", userInfo.getUserId()); startActivity(intent); } }); // 粉丝列表 view.findViewById(R.id.ln_fans).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(getActivity(), FollowFansActivity.class); intent.putExtra("mType", "1"); // 1=粉丝列表 intent.putExtra("user_id", userInfo.getUserId()); startActivity(intent); } }); ``` --- ## 🔄 完整业务流程 ``` 用户从MeFragment点击关注/粉丝 ↓ 传递参数:mType(1或2)、user_id ↓ FollowFansActivity初始化 ↓ 设置标题(根据mType) ↓ 初始化RecyclerView和Adapter ↓ 调用getPublish()获取第一页数据 ↓ 显示列表数据 ↓ 下拉刷新 → 重置页码为1 → 重新获取数据 上拉加载 → 页码+1 → 加载更多数据 ↓ 点击头像 → 跳转UserInfoActivity 点击关注按钮 → 跳转InviteFriendActivity ``` --- ## 📐 UI组件 ### 布局文件 - **布局文件**:`activity_follow_fans.xml` - **主要组件**: - `Toolbar`:标题栏 - `SmartRefreshLayout`:下拉刷新和上拉加载容器 - `RecyclerView`:列表展示 ### 列表项布局 - **布局文件**:`adapter_follow_fans_item.xml` - **显示内容**: - 头像(`img_ada_head`) - 昵称(`tv_ada_name`) - 粉丝数(`tv_ada_number`) - 关注按钮(`tv_ada_follow`) --- ## 💾 数据模型 ### GetFollowFansResult ```java public class GetFollowFansResult extends StatusResult { private List list; public static class ListBean { private String id; // 用户ID private String nickname; // 昵称 private String avatar; // 头像URL private int gender; // 性别 private Object city; // 城市 private int fans_c; // 粉丝数 private boolean both_follow; // 是否互相关注 private String prevtime_text; // 上次活跃时间文本 private String logintime_text; // 登录时间文本 private String jointime_text; // 加入时间文本 } } ``` ### 关键字段说明 - **`both_follow`**:是否互相关注 - `true`:互相关注 - `false`:单向关注或未关注 --- ## 🔧 核心方法 ### 1. 初始化 (`bindEvents()`) ```java @Override protected void bindEvents() { super.bindEvents(); // 获取Intent参数 mType = getIntent().getStringExtra("mType"); user_id = getIntent().getStringExtra("user_id"); // 根据类型设置标题 if ("1".equals(mType)){ setToolBarTitle("我的粉丝"); } else if ("2".equals(mType)){ setToolBarTitle("我的关注"); } // 初始化RecyclerView initRcyItem(); // 获取第一页数据 getPublish(); // 设置下拉刷新 swipeRefreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh(@NonNull RefreshLayout refreshLayout) { mPage = 1; // 重置页码 getPublish(); // 重新获取数据 } }); // 设置上拉加载 swipeRefreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore(@NonNull RefreshLayout refreshLayout) { mPage++; // 页码+1 getPublish(); // 加载更多数据 } }); } ``` **说明**: - 从Intent获取 `mType` 和 `user_id` - 根据 `mType` 设置标题 - 初始化列表和刷新控件 --- ### 2. 初始化RecyclerView (`initRcyItem()`) ```java private void initRcyItem(){ rcy_item.setLayoutManager(new LinearLayoutManager(mContext)); mBaseAdapter = new BaseRcyAdapter(null, R.layout.adapter_follow_fans_item) { @Override public void bindView(@NonNull BaseViewHolder holder, int position) { GetFollowFansResult.ListBean listBean = (GetFollowFansResult.ListBean) this.getmData().get(position); // 1. 设置基本信息 holder.setText(R.id.tv_ada_name, listBean.getNickname()); holder.setText(R.id.tv_ada_number, listBean.getFans_c() + " 粉丝"); // 2. 设置头像 ImageView imageView = (ImageView) holder.getView(R.id.img_ada_head); GlideUtils.loadRoundedCornerImage(mContext, AppService.APP_FILE_ADDRESS + listBean.getAvatar(), imageView); // 3. 设置关注按钮状态(根据mType和both_follow) TextView tvFollow = (TextView) holder.getView(R.id.tv_ada_follow); if ("1".equals(mType)) { // 粉丝列表:显示关注按钮状态 if (listBean.isBoth_follow()) { // 互相关注 tvFollow.setTextColor(getResources().getColor(R.color.color_3333)); tvFollow.setBackground(getResources().getDrawable(R.drawable.btn_submit_qian_style)); holder.setText(R.id.tv_ada_follow, "互相关注"); } else { // 未关注,显示关注按钮(可点击) tvFollow.setTextColor(getResources().getColor(R.color.white)); tvFollow.setBackground(getResources().getDrawable(R.drawable.btn_submit_style)); holder.setText(R.id.tv_ada_follow, "关注"); holder.setOnClickListener(R.id.tv_ada_follow, new View.OnClickListener() { @Override public void onClick(View view) { // 跳转到添加好友页面 UserViewModel userViewModel = ViewModelProviders.of(FollowFansActivity.this).get(UserViewModel.class); UserInfo userInfo = userViewModel.getUserInfo(listBean.getId(), true); if (userInfo == null) { return; } Intent intent = new Intent(mContext, InviteFriendActivity.class); intent.putExtra("userInfo", userInfo); startActivity(intent); } }); } } else if ("2".equals(mType)) { // 关注列表:显示关注状态 if (listBean.isBoth_follow()) { // 互相关注 tvFollow.setTextColor(getResources().getColor(R.color.color_3333)); tvFollow.setBackground(getResources().getDrawable(R.drawable.btn_submit_qian_style)); holder.setText(R.id.tv_ada_follow, "互相关注"); } else { // 已关注(单向) tvFollow.setTextColor(getResources().getColor(R.color.color_3333)); tvFollow.setBackground(getResources().getDrawable(R.drawable.btn_submit_qian_style)); holder.setText(R.id.tv_ada_follow, "已关注"); } } // 4. 点击头像查看用户详情 holder.setOnClickListener(R.id.img_ada_head, new View.OnClickListener() { @Override public void onClick(View view) { UserViewModel userViewModel = ViewModelProviders.of(FollowFansActivity.this).get(UserViewModel.class); UserInfo userInfo = userViewModel.getUserInfo(listBean.getId(), true); if (userInfo == null) { return; } Intent intent = new Intent(mContext, UserInfoActivity.class); intent.putExtra("userInfo", userInfo); startActivity(intent); } }); } }; rcy_item.setAdapter(mBaseAdapter); } ``` **关键逻辑**: #### 2.1 关注按钮状态(粉丝列表 mType="1") - **互相关注** (`both_follow = true`): - 显示"互相关注" - 灰色背景,深色文字 - **不可点击** - **未关注** (`both_follow = false`): - 显示"关注" - 蓝色背景,白色文字 - **可点击**:跳转到 `InviteFriendActivity` 添加好友 #### 2.2 关注按钮状态(关注列表 mType="2") - **互相关注** (`both_follow = true`): - 显示"互相关注" - 灰色背景,深色文字 - **已关注** (`both_follow = false`): - 显示"已关注" - 灰色背景,深色文字 - **不可点击**(单向关注) #### 2.3 点击头像 - 获取用户信息(`UserViewModel.getUserInfo()`) - 跳转到 `UserInfoActivity` 查看用户详情 --- ### 3. 获取数据 (`getPublish()`) ```java private void getPublish(){ HashMap headParams = new HashMap<>(); // 类型1=粉丝列表 2=关注列表 3=点赞列表 headParams.put("type", mType); headParams.put("page", mPage + ""); headParams.put("limit", AppService.PAGE_MAX_NUMBER + ""); headParams.put("user_id", user_id); AppService.Instance().interactiveList(headParams, new SimpleCallback() { @Override public void onUiSuccess(GetFollowFansResult result) { // 结束刷新和加载更多 if (swipeRefreshLayout != null) { swipeRefreshLayout.finishRefresh(); swipeRefreshLayout.finishLoadMore(); } GetFollowFansResult data = result.getData(); if (mPage == 1) { // 第一页:替换数据 if (data != null) { ArrayList list = (ArrayList) data.getList(); mBaseAdapter.setmData(list); } } else { // 加载更多:追加数据 ArrayList list = (ArrayList) data.getList(); mBaseAdapter.setLoadmData(list); } } @Override public void onUiFailure(int code, String msg) { // 结束刷新和加载更多 if (swipeRefreshLayout != null) { swipeRefreshLayout.finishRefresh(); swipeRefreshLayout.finishLoadMore(); } showToast(msg); } }); } ``` **API信息**: - **接口路径**:`/api/interactive/list`(`Api.interactiveList`) - **请求方法**:POST - **请求参数**: ```java { "type": "1" 或 "2", // 类型:1=粉丝列表,2=关注列表 "page": "1", // 页码 "limit": "20", // 每页数量(AppService.PAGE_MAX_NUMBER) "user_id": "用户ID" // 要查询的用户ID } ``` **数据处理**: - **第一页** (`mPage == 1`):使用 `setmData()` 替换整个列表 - **加载更多** (`mPage > 1`):使用 `setLoadmData()` 追加数据到列表 --- ## 🔄 刷新和加载更多 ### 下拉刷新 ```java swipeRefreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh(@NonNull RefreshLayout refreshLayout) { mPage = 1; // 重置页码为1 getPublish(); // 重新获取数据 } }); ``` **流程**: 1. 用户下拉刷新 2. 重置页码为1 3. 调用 `getPublish()` 获取第一页数据 4. 使用 `setmData()` 替换列表数据 5. 调用 `swipeRefreshLayout.finishRefresh()` 结束刷新 ### 上拉加载更多 ```java swipeRefreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore(@NonNull RefreshLayout refreshLayout) { mPage++; // 页码+1 getPublish(); // 加载更多数据 } }); ``` **流程**: 1. 用户上拉到底部 2. 页码+1 3. 调用 `getPublish()` 获取下一页数据 4. 使用 `setLoadmData()` 追加数据到列表 5. 调用 `swipeRefreshLayout.finishLoadMore()` 结束加载 --- ## 🎨 UI状态说明 ### 关注按钮样式 #### 1. 互相关注(灰色背景) ```java tvFollow.setTextColor(getResources().getColor(R.color.color_3333)); // 深色文字 tvFollow.setBackground(getResources().getDrawable(R.drawable.btn_submit_qian_style)); // 灰色背景 holder.setText(R.id.tv_ada_follow, "互相关注"); ``` - **显示**:"互相关注" - **状态**:不可点击 #### 2. 关注按钮(蓝色背景) ```java tvFollow.setTextColor(getResources().getColor(R.color.white)); // 白色文字 tvFollow.setBackground(getResources().getDrawable(R.drawable.btn_submit_style)); // 蓝色背景 holder.setText(R.id.tv_ada_follow, "关注"); ``` - **显示**:"关注" - **状态**:可点击(跳转到添加好友页面) - **位置**:仅在粉丝列表(mType="1")中,且未关注时显示 #### 3. 已关注(灰色背景) ```java tvFollow.setTextColor(getResources().getColor(R.color.color_3333)); // 深色文字 tvFollow.setBackground(getResources().getDrawable(R.drawable.btn_submit_qian_style)); // 灰色背景 holder.setText(R.id.tv_ada_follow, "已关注"); ``` - **显示**:"已关注" - **状态**:不可点击 - **位置**:在关注列表(mType="2")中,且单向关注时显示 --- ## 📝 关键字段和变量 ### 成员变量 ```java private RecyclerView rcy_item; // 列表RecyclerView private BaseRcyAdapter mBaseAdapter; // 列表适配器 private SmartRefreshLayout swipeRefreshLayout; // 下拉刷新控件 private int mPage = 1; // 当前页码 private String mType = ""; // 类型:1=粉丝,2=关注 private String user_id; // 用户ID ``` ### Intent参数 - **`mType`**:类型("1"=粉丝列表,"2"=关注列表) - **`user_id`**:要查询的用户ID --- ## 🔗 关联页面 ### 1. 跳转来源 - **`MeFragment`**:我的页面 - 点击"关注" → `mType="2"` - 点击"粉丝" → `mType="1"` ### 2. 跳转目标 - **`UserInfoActivity`**:点击头像查看用户详情 - **`InviteFriendActivity`**:点击关注按钮添加好友(仅粉丝列表中未关注的用户) --- ## ⚠️ 注意事项 ### 1. 数据分页 - 使用 `AppService.PAGE_MAX_NUMBER` 作为每页数量 - 第一页使用 `setmData()` 替换数据 - 后续页使用 `setLoadmData()` 追加数据 ### 2. 刷新状态管理 - 请求成功后必须调用 `finishRefresh()` 和 `finishLoadMore()` - 请求失败时也要调用,避免刷新控件一直显示 ### 3. 用户信息获取 - 点击头像或关注按钮时,需要先通过 `UserViewModel.getUserInfo()` 获取用户信息 - 如果 `userInfo` 为 `null`,则不执行跳转 ### 4. 关注按钮逻辑 - **粉丝列表**:未关注时显示可点击的"关注"按钮 - **关注列表**:所有项都显示状态(互相关注/已关注),不可点击 ### 5. 状态栏设置 - 使用白色背景,深色图标:`setTitleBackgroundResource(R.color.white, false)` --- ## 📊 数据流程总结 ``` 用户操作 ↓ 获取Intent参数(mType, user_id) ↓ 设置标题(根据mType) ↓ 初始化RecyclerView和Adapter ↓ 调用API获取第一页数据 ↓ 显示列表(头像、昵称、粉丝数、关注状态) ↓ 用户交互: - 下拉刷新 → 重置页码 → 重新获取 - 上拉加载 → 页码+1 → 追加数据 - 点击头像 → 查看用户详情 - 点击关注(粉丝列表) → 添加好友 ``` --- ## 🔍 相关文件 - **Activity**:`uikit/src/main/java/cn/wildfire/chat/kit/user/FollowFansActivity.java` - **布局文件**:`uikit/src/main/res/layout/activity_follow_fans.xml` - **列表项布局**:`uikit/src/main/res/layout/adapter_follow_fans_item.xml` - **数据模型**:`uikit/src/main/java/cn/wildfire/chat/kit/net/model/GetFollowFansResult.java` - **API服务**:`uikit/src/main/java/cn/wildfire/chat/kit/net/AppService.java` - **跳转来源**:`app/src/main/java/com/xunpaisoft/social/im/main/MeFragment.java` --- ## 💡 技术要点 1. **SmartRefreshLayout**:用于下拉刷新和上拉加载 2. **BaseRcyAdapter**:自定义的RecyclerView适配器 3. **分页加载**:通过页码控制数据加载 4. **条件渲染**:根据 `mType` 和 `both_follow` 显示不同的按钮状态 5. **Glide图片加载**:使用 `GlideUtils.loadRoundedCornerImage()` 加载圆角头像 6. **ViewModel获取用户信息**:使用 `UserViewModel` 获取用户信息用于跳转 --- ## 📌 总结 `FollowFansActivity` 是一个功能完整的关注/粉丝列表页面,支持: - ✅ 两种列表类型(关注/粉丝) - ✅ 分页加载数据 - ✅ 下拉刷新和上拉加载更多 - ✅ 关注操作(粉丝列表) - ✅ 用户详情查看 - ✅ 动态按钮状态显示 整个页面逻辑清晰,用户体验良好,代码结构合理。