Files
zhini_im/MeFragment我的页面逻辑分析.txt

547 lines
16 KiB
Plaintext
Raw Permalink Normal View History

# 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`等)
- 可能是功能未完成或暂时隐藏