# 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 params = new HashMap<>(); params.put("user_id", Constants.getUserId()); AppService.Instance().getFans(params, new SimpleCallback() { @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() { @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() { @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> userInfoLiveDataObserver = new Observer>() { @Override public void onChanged(@Nullable List 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) ↓ 更新UI(updateUserInfo) ↓ 获取统计数据(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> userInfoLiveDataObserver = new Observer>() { // 观察用户信息列表,找到自己的信息并更新UI }; ``` --- ## 🐛 潜在问题 1. **性别图标显示**: - 性别信息通过单独的API获取,可能存在延迟 - 如果API失败,性别图标不会显示 2. **统计数据更新**: - 统计数据需要单独API调用,可能与用户信息不同步 - 如果API失败,统计数据显示为默认值(可能为空) 3. **主题切换**: - 切换主题需要重启应用,用户体验不够流畅 - 可以考虑使用动态主题,无需重启 4. **功能入口隐藏**: - 部分功能入口已隐藏(`accountOptionItemView`、`favOptionItemView`等) - 可能是功能未完成或暂时隐藏