Files
zhini_im/FollowFansActivity关注粉丝列表页面逻辑分析.txt

556 lines
18 KiB
Plaintext
Raw Normal View History

# 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点击关注/粉丝
传递参数mType1或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<GetFollowFansResult> {
private List<ListBean> 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<String,String> 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<GetFollowFansResult>() {
@Override
public void onUiSuccess(GetFollowFansResult result) {
// 结束刷新和加载更多
if (swipeRefreshLayout != null) {
swipeRefreshLayout.finishRefresh();
swipeRefreshLayout.finishLoadMore();
}
GetFollowFansResult data = result.getData();
if (mPage == 1) {
// 第一页:替换数据
if (data != null) {
ArrayList<GetFollowFansResult.ListBean> list =
(ArrayList<GetFollowFansResult.ListBean>) data.getList();
mBaseAdapter.setmData(list);
}
} else {
// 加载更多:追加数据
ArrayList<GetFollowFansResult.ListBean> list =
(ArrayList<GetFollowFansResult.ListBean>) 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` 是一个功能完整的关注/粉丝列表页面,支持:
- ✅ 两种列表类型(关注/粉丝)
- ✅ 分页加载数据
- ✅ 下拉刷新和上拉加载更多
- ✅ 关注操作(粉丝列表)
- ✅ 用户详情查看
- ✅ 动态按钮状态显示
整个页面逻辑清晰,用户体验良好,代码结构合理。