Files
zhini_im/MeFragment我的页面逻辑分析.txt
rw0067680 c01808ac21 first commit
Change-Id: Ib7c2ab10a2562044fcaf9879388a6cbc1db6ac61
2025-12-23 10:00:49 +08:00

547 lines
16 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MeFragment 我的页面逻辑分析
## 📋 页面概述
**文件位置**: `app/src/main/java/com/xunpaisoft/social/im/main/MeFragment.java`
**布局文件**: `app/src/main/res/layout/main_fragment_me.xml`
**页面类型**: Fragment
**主要功能**: "我的"页面,显示用户个人信息、统计数据,提供各种功能入口
---
## 🎯 核心功能模块
### 1. 页面初始化
#### 1.1 生命周期方法
```java
@Override
public View onCreateView(...) {
View view = inflater.inflate(R.layout.main_fragment_me, container, false);
bindViews(view); // 绑定视图
bindEvents(view); // 绑定事件
init(); // 初始化数据
return view;
}
```
#### 1.2 数据初始化 (`init()`)
```java
// 1. 获取UserViewModel
userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
// 2. 异步获取用户信息
userViewModel.getUserInfoAsync(userViewModel.getUserId(), true)
.observe(getViewLifecycleOwner(), info -> {
userInfo = info;
if (userInfo != null) {
updateUserInfo(userInfo); // 更新UI
}
});
// 3. 观察用户信息变化(实时更新)
userViewModel.userInfoLiveData().observeForever(userInfoLiveDataObserver);
// 4. 根据服务器类型显示/隐藏文件记录选项
if (ChatManager.Instance().isCommercialServer()) {
fileRecordOptionItem.setVisibility(View.VISIBLE);
} else {
fileRecordOptionItem.setVisibility(View.GONE);
}
// 5. 监听用户信息更新事件
LiveDataBus.get().with(Constants.USERINFO_UPDATE).observe(...);
```
---
### 2. 用户信息显示 (`updateUserInfo()`)
#### 2.1 基本信息显示
```java
// 1. 头像显示使用Glide加载圆角处理
RequestOptions options = new RequestOptions()
.placeholder(R.mipmap.icon_default_man) // 占位图
.transforms(new CenterCrop(), new RoundedCorners(30)); // 圆角30px
Glide.with(this)
.load(userInfo.portrait)
.apply(options)
.into(portraitImageView);
// 2. 昵称显示
nameTextView.setText(userInfo.displayName);
// 3. 账号显示
accountTextView.setText("账号: " + userInfo.name);
```
#### 2.2 统计数据获取
```java
// 调用API获取关注、粉丝、点赞数量
Map<String, String> params = new HashMap<>();
params.put("user_id", Constants.getUserId());
AppService.Instance().getFans(params, new SimpleCallback<UserInfoNumberResult>() {
@Override
public void onUiSuccess(UserInfoNumberResult result) {
UserInfoNumberResult data = result.getData();
tvGunZhu.setText(data.getFollow_c()); // 关注数
tvFensi.setText(data.getFans_c()); // 粉丝数
tvDianZan.setText(data.getLikes_c()); // 点赞数
}
});
```
#### 2.3 性别显示
```java
// 获取其他用户信息(用于获取性别)
getOtherUserInfo(userInfo.uid, "1");
// 在getOtherUserInfo回调中
if ("1".equals(data.getGender())) {
// 女性
imgSex.setImageDrawable(getActivity().getDrawable(R.mipmap.icon_sex_woman));
} else {
// 男性
imgSex.setImageDrawable(getActivity().getDrawable(R.mipmap.icon_sex_man));
}
```
---
### 3. 页面刷新逻辑
#### 3.1 Fragment可见性控制
```java
@Override
public void setMenuVisibility(boolean isvisible) {
super.setMenuVisibility(isvisible);
this.isVisibleToUser = isvisible; // 记录Fragment是否对用户可见
}
```
#### 3.2 onResume刷新
```java
@Override
public void onResume() {
super.onResume();
if (this.isVisibleToUser && userViewModel != null) {
// Fragment可见时刷新用户信息
userViewModel.getUserInfoAsync(userViewModel.getUserId(), true)
.observe(getViewLifecycleOwner(), info -> {
userInfo = info;
if (userInfo != null) {
updateUserInfo(userInfo);
}
});
}
}
```
#### 3.3 LiveDataBus监听
```java
// 监听用户信息更新事件
LiveDataBus.get().with(Constants.USERINFO_UPDATE).observe(getActivity(), new Observer<Object>() {
@Override
public void onChanged(Object o) {
// 用户信息更新时,重新获取其他用户信息(更新性别等)
getOtherUserInfo(userInfo.uid, "1");
}
});
```
---
### 4. 功能入口(事件绑定)
#### 4.1 个人信息入口
```java
view.findViewById(R.id.meLinearLayout).setOnClickListener(v -> showMyInfo());
void showMyInfo() {
Intent intent = new Intent(getActivity(), UserInfoActivity.class);
userInfo.setSourceType(1); // 设置来源类型为个人信息页面
intent.putExtra("userInfo", userInfo);
startActivity(intent);
}
```
- **功能**:跳转到 `UserInfoActivity` 查看自己的详细信息
#### 4.2 关注/粉丝列表
```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);
}
});
```
- **功能**:跳转到 `FollowFansActivity` 查看关注/粉丝列表
- **参数说明**
- `mType = "1"`:粉丝列表
- `mType = "2"`:关注列表
#### 4.3 相册入口
```java
view.findViewById(R.id.accountPhoto).setOnClickListener(view1 ->
startActivity(new Intent(getActivity(), UserAlbumManageActivity.class))
);
```
- **功能**:跳转到 `UserAlbumManageActivity` 管理相册
#### 4.4 其他功能入口
| 功能 | ID | 跳转页面 | 说明 |
|------|-----|---------|------|
| 收藏 | `favOptionItemView` | `FavoriteListActivity` | 收藏列表 |
| 账号与安全 | `accountOptionItemView` | `AccountActivity` | 账号安全管理(已隐藏) |
| 文件记录 | `fileRecordOptionItemView` | `FileRecordListActivity` | 文件记录(仅商业服务器) |
| 主题 | `themeOptionItemView` | 主题选择对话框 | 切换深色/浅色主题 |
| 设置 | `settingOptionItemView` | `SettingActivity` | 设置页面 |
| 消息通知 | `notificationOptionItemView` | `MessageNotifySettingActivity` | 消息通知设置 |
| 联系我们 | `accountAbout` | `ConversationActivity` | 客服对话单聊ID"47" |
#### 4.5 VIP功能
```java
view.findViewById(R.id.rl_vip).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 跳转到WebView页面邀请好友页面
WfcWebViewActivity.loadUrl(getActivity(), "", "https://xingyao.xunpaisoft.com");
}
});
```
- **功能**点击VIP区域跳转到邀请好友页面WebView
---
### 5. 主题切换功能 (`theme()`)
```java
void theme() {
SharedPreferences sp = getActivity().getSharedPreferences("wfc_kit_config", Context.MODE_PRIVATE);
boolean darkTheme = sp.getBoolean("darkTheme", true); // 获取当前主题
// 显示主题选择对话框
new MaterialDialog.Builder(getContext())
.items(R.array.themes) // 主题列表:深色/浅色
.itemsCallback(new MaterialDialog.ListCallback() {
@Override
public void onSelection(MaterialDialog dialog, View v, int position, CharSequence text) {
if (position == 0 && darkTheme) {
// 选择浅色主题,当前是深色
sp.edit().putBoolean("darkTheme", false).apply();
restart(); // 重启应用使主题生效
}
if (position == 1 && !darkTheme) {
// 选择深色主题,当前是浅色
sp.edit().putBoolean("darkTheme", true).apply();
restart();
}
}
}).show();
}
private void restart() {
// 重启应用
Intent i = getActivity().getApplicationContext().getPackageManager()
.getLaunchIntentForPackage(getActivity().getApplicationContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
```
**说明**
- 主题保存在 `SharedPreferences` 中key为 `"darkTheme"`
- 切换主题后需要重启应用才能生效
- 使用 `FLAG_ACTIVITY_CLEAR_TOP` 清除Activity栈确保应用完全重启
---
### 6. 其他用户信息获取 (`getOtherUserInfo()`)
```java
private void getOtherUserInfo(String user_id, String is_frient) {
AppService.Instance().getUserInfo(user_id, is_frient, new SimpleCallback<GetUserInfoResult>() {
@Override
public void onUiSuccess(GetUserInfoResult infoResult) {
if (getActivity() == null || isDetached() || isRemoving()) {
return; // Fragment已销毁不更新UI
}
if (infoResult != null) {
GetUserInfoResult data = infoResult.getData();
// 根据性别显示性别图标
if (!TextUtils.isEmpty(data.getGender())) {
if ("1".equals(data.getGender())) {
// 女性
imgSex.setImageDrawable(getActivity().getDrawable(R.mipmap.icon_sex_woman));
} else {
// 男性
imgSex.setImageDrawable(getActivity().getDrawable(R.mipmap.icon_sex_man));
}
}
}
}
});
}
```
**功能**
- 获取用户的详细信息(性别等)
- 主要用于显示性别图标
- 参数说明:
- `user_id`用户ID
- `is_frient`:是否好友("1"=是好友,"0"=非好友)
---
### 7. 观察者模式 - 用户信息实时更新
```java
private Observer<List<UserInfo>> userInfoLiveDataObserver = new Observer<List<UserInfo>>() {
@Override
public void onChanged(@Nullable List<UserInfo> userInfos) {
if (userInfos == null) {
return;
}
// 遍历用户信息列表,找到自己的信息
for (UserInfo info : userInfos) {
if (info.uid.equals(userViewModel.getUserId())) {
userInfo = info;
updateUserInfo(userInfo); // 更新UI
break;
}
}
}
};
```
**说明**
- 观察 `userViewModel.userInfoLiveData()`当用户信息发生变化时自动更新UI
- 在 `onDestroyView()` 中需要移除观察者,避免内存泄漏
---
## 🔄 完整业务流程
### 场景1页面初始化
```
Fragment创建onCreateView
绑定视图bindViews
绑定事件bindEvents
初始化数据init
获取用户信息UserViewModel.getUserInfoAsync
更新UIupdateUserInfo
获取统计数据getFans API
获取其他用户信息getOtherUserInfo API
显示用户信息、统计数据、性别图标
```
### 场景2页面刷新Fragment可见时
```
Fragment可见setMenuVisibility(true)
onResume触发
检查Fragment是否可见isVisibleToUser
重新获取用户信息
更新UI
```
### 场景3用户信息更新从其他页面返回
```
其他页面修改用户信息
发送LiveDataBus事件Constants.USERINFO_UPDATE
MeFragment监听到事件
重新获取其他用户信息getOtherUserInfo
更新性别图标等UI
```
---
## 📊 数据结构
### API返回数据结构
#### 1. getFans API (`UserInfoNumberResult`)
```java
UserInfoNumberResult {
String follow_c; // 关注数
String fans_c; // 粉丝数
String likes_c; // 点赞数
}
```
#### 2. getUserInfo API (`GetUserInfoResult`)
```java
GetUserInfoResult {
String id;
String nickname;
String avatar;
String gender; // 性别("1"=女性,"0"或其他=男性)
String province;
String city;
String district;
String[] photos; // 相册照片数组
// ... 其他字段
}
```
---
## 🛠️ 技术要点
### 1. ViewModel + LiveData
- 使用 `UserViewModel` 管理用户信息
- 使用 `LiveData` 观察用户信息变化
- 自动更新UI无需手动刷新
### 2. Fragment生命周期管理
- 使用 `getViewLifecycleOwner()` 确保观察者生命周期与Fragment绑定
- 在 `onDestroyView()` 中移除观察者,避免内存泄漏
- 检查Fragment状态`isDetached()`, `isRemoving()`避免更新已销毁的Fragment
### 3. Glide图片加载
- 使用Glide加载用户头像
- 自定义RequestOptions占位图、圆角处理30px
### 4. LiveDataBus事件总线
- 使用 `LiveDataBus` 监听用户信息更新事件
- 实现跨页面数据同步
### 5. 主题切换
- 使用 `SharedPreferences` 保存主题设置
- 切换主题后重启应用使主题生效
---
## ⚠️ 注意事项
1. **Fragment生命周期**
- 在异步回调中检查Fragment状态避免更新已销毁的Fragment
- 使用 `getViewLifecycleOwner()` 确保观察者自动移除
2. **观察者移除**
- `observeForever` 需要在 `onDestroyView()` 中手动移除
- `observe` 会在Fragment销毁时自动移除
3. **统计数据更新**
- 关注、粉丝、点赞数通过API获取不在用户信息中
- 需要单独调用 `getFans` API获取
4. **性别显示**
- 性别信息不在 `UserInfo` 中,需要通过 `getOtherUserInfo` API获取
- 性别值为 `"1"` 表示女性,其他值表示男性
5. **功能入口可见性**
- `fileRecordOptionItem` 仅在商业服务器时显示
- `accountOptionItemView` 当前已隐藏(`visibility="gone"`
- `favOptionItemView`、`themeOptionItemView` 等部分功能已隐藏
6. **客服对话**
- "联系我们"功能跳转到与用户ID为 `"47"` 的单聊会话
- 这是一个系统用户(客服)
---
## 🔍 相关文件
- **布局文件**`app/src/main/res/layout/main_fragment_me.xml`
- **ViewModel**`UserViewModel` - 用户信息管理
- **相关页面**
- `UserInfoActivity` - 个人信息详情
- `FollowFansActivity` - 关注/粉丝列表
- `UserAlbumManageActivity` - 相册管理
- `AccountActivity` - 账号安全
- `SettingActivity` - 设置
- `FavoriteListActivity` - 收藏列表
- `FileRecordListActivity` - 文件记录
- `MessageNotifySettingActivity` - 消息通知设置
---
## 📝 代码关键位置
### 初始化第252-275行
```java
private void init() {
// 获取UserViewModel
// 获取用户信息
// 观察用户信息变化
// 监听用户信息更新事件
}
```
### 更新用户信息第204-250行
```java
private void updateUserInfo(UserInfo userInfo) {
// 显示头像、昵称、账号
// 获取统计数据
// 获取其他用户信息(性别)
}
```
### 事件绑定第140-186行
```java
private void bindEvents(View view) {
// 绑定各种功能入口的点击事件
}
```
### 用户信息观察者第92-107行
```java
private Observer<List<UserInfo>> userInfoLiveDataObserver = new Observer<List<UserInfo>>() {
// 观察用户信息列表找到自己的信息并更新UI
};
```
---
## 🐛 潜在问题
1. **性别图标显示**
- 性别信息通过单独的API获取可能存在延迟
- 如果API失败性别图标不会显示
2. **统计数据更新**
- 统计数据需要单独API调用可能与用户信息不同步
- 如果API失败统计数据显示为默认值可能为空
3. **主题切换**
- 切换主题需要重启应用,用户体验不够流畅
- 可以考虑使用动态主题,无需重启
4. **功能入口隐藏**
- 部分功能入口已隐藏(`accountOptionItemView`、`favOptionItemView`等)
- 可能是功能未完成或暂时隐藏