# PublishActivity 发布帖子页面逻辑分析 ## 📋 页面概述 **文件位置**: `uikit/src/main/java/cn/wildfire/chat/kit/user/PublishActivity.java` **布局文件**: `uikit/src/main/res/layout/activity_publish.xml` **页面类型**: Activity(继承自 WfcBaseActivity) **主要功能**: 发布朋友圈动态,支持文字和图片内容发布 --- ## 🎯 核心功能模块 ### 1. 页面初始化 (`afterViews()`) #### 1.1 UI组件初始化 ```java mRecyPicItem = findViewById(R.id.rcy_pic_item); // 图片选择RecyclerView mEdtContent = findViewById(R.id.edt_content); // 内容输入框 oiv_show = findViewById(R.id.oiv_show); // 可见范围设置(默认隐藏) ``` #### 1.2 状态栏设置 ```java setTitleBackgroundResource(R.color.white, false); // 白色状态栏,深色图标 ``` #### 1.3 初始化操作 - ✅ 获取七牛云Token:`getQnToken()` - 用于图片上传 - ✅ 初始化图片选择器:`initWidget()` - 设置RecyclerView和适配器 - ✅ 设置默认可见范围:`oiv_show.setDesc("公开")` - 默认值为"公开"(`mShowType = "1"`) --- ### 2. 图片选择功能 (`initWidget()`) #### 2.1 RecyclerView配置 ```java // 网格布局:3列,垂直方向 FunctionBackGridLayoutManager manager = new FunctionBackGridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false); mRecyPicItem.setLayoutManager(manager); // 适配器配置 adapter = new FunctionBackImageAdapter(this, onAddPicClickListener); adapter.setList(selectList); // 设置图片列表 adapter.setSelectMax(MAX_SELECT_NUM); // 最大选择数量:9张 mRecyPicItem.setAdapter(adapter); ``` #### 2.2 关键常量 - `MAX_SELECT_NUM = 9`:最多选择9张图片 - `MIN_SELECT_NUM = 1`:最少选择1张图片 - `SPAN_COUNT_NUM = 3`:每行显示3张图片 #### 2.3 图片选择回调 (`onAddPicClickListener`) 当用户点击"添加图片"按钮时: 1. 计算可选择的图片数量:`number = MAX_SELECT_NUM - selectList.size()` 2. 显示选择对话框:`CameraSelectDialog` - 提供"拍照"和"从相册选择"两个选项 --- ### 3. 图片上传流程 #### 3.1 上传步骤 **步骤1:选择图片** - **拍照**:`PictureSelector.create().openCamera()` - 调用系统相机 - **相册选择**:`PictureSelector.create().openGallery()` - 打开相册选择 **步骤2:图片压缩** ```java Luban.with(mContext) .load(realPath) // 加载原始图片路径 .setCompressListener(...) // 设置压缩监听器 .launch(); // 启动压缩 ``` - 使用 `Luban` 库进行图片压缩,减小上传文件大小 **步骤3:上传到七牛云** ```java QiniuUploadFile.uploadFile( file.getName(), // 文件名 mQnToken, // 七牛云Token(从服务器获取) file, // 压缩后的文件 new UploadCallBack() { // 上传回调 @Override public void result(boolean isSuccess, String address) { // 上传成功,address为图片URL // 创建PhotoInfoEntity并添加到列表 PhotoInfoEntity photoInfoEntity = new PhotoInfoEntity() .setUrl(address) // 完整URL .setMinUrl(address); // 缩略图URL(当前使用相同URL) arrayListPhoto.add(photoInfoEntity); adapter.setList(arrayListPhoto); adapter.notifyDataSetChanged(); } } ); ``` #### 3.2 数据结构 ```java PhotoInfoEntity { String url; // 图片完整URL String minUrl; // 图片缩略图URL } ``` --- ### 4. 发布功能 (`setToolbarSave` 点击事件) #### 4.1 数据收集 ```java String content = mEdtContent.getText().toString().trim(); // 获取文字内容 HashMap headMaps = new HashMap<>(); // 1. 添加文字内容 headMaps.put("content", content); // 2. 添加可见范围(1:公开, 2:仅好友可见) headMaps.put("ispravite", mShowType); // 3. 添加图片URL列表(逗号分隔) if(adapter != null) { List list = adapter.getList(); StringBuffer listBuffer = new StringBuffer(); for (int i = 0; i < list.size(); i++) { PhotoInfoEntity photoInfoEntity = list.get(i); if ((list.size() - 1) == i) { listBuffer.append(photoInfoEntity.getUrl()); // 最后一张不加逗号 } else { listBuffer.append(photoInfoEntity.getUrl()).append(","); // 其他加逗号 } } headMaps.put("images", listBuffer.toString()); // 图片URL列表,格式:url1,url2,url3 } // 4. 添加定位信息(从本地SharedPreferences读取,如果存在) String latitude = SharedPreferencesUtils.getString("location_latitude", ""); String longitude = SharedPreferencesUtils.getString("location_longitude", ""); String poi = SharedPreferencesUtils.getString("location_poi", ""); // 5. 添加省市区信息(优先使用定位获取的,如果为空则使用用户手动设置的) String province = SharedPreferencesUtils.getString("location_province", ""); String city = SharedPreferencesUtils.getString("location_city", ""); String district = SharedPreferencesUtils.getString("location_district", ""); // 如果定位的省市区为空,则使用用户手动设置的省市区 if (TextUtils.isEmpty(province)) { province = SharedPreferencesUtils.getString("user_province", ""); } if (TextUtils.isEmpty(city)) { city = SharedPreferencesUtils.getString("user_city", ""); } if (TextUtils.isEmpty(district)) { district = SharedPreferencesUtils.getString("user_district", ""); } // 添加定位信息(如果存在) if (!TextUtils.isEmpty(latitude)) { headMaps.put("lat", latitude); } if (!TextUtils.isEmpty(longitude)) { headMaps.put("lng", longitude); } if (!TextUtils.isEmpty(poi)) { headMaps.put("poi", poi); } // 添加省市区信息(如果存在) if (!TextUtils.isEmpty(province)) { headMaps.put("province", province); } if (!TextUtils.isEmpty(city)) { headMaps.put("city", city); } if (!TextUtils.isEmpty(district)) { headMaps.put("district", district); } ``` #### 4.2 数据验证 ```java if (TextUtils.isEmpty(content) && TextUtils.isEmpty(listBuffer.toString())) { ToastUtils.showToast(PublishActivity.this, "发布内容为空!"); return; // 文字和图片都为空,不允许发布 } ``` #### 4.3 提交发布请求 ```java AppService.Instance().publishContent(headMaps, new SimpleCallback() { @Override public void onUiSuccess(Object o) { showToast("发布成功"); finish(); // 发布成功,关闭页面 } @Override public void onUiFailure(int code, String msg) { showToast(msg); // 显示错误信息 } }); ``` --- ### 5. 可见范围设置 (`bindEvents()`) #### 5.1 可见范围选项 - **"公开"** (`mShowType = "1"`):所有人可见 - **"仅好友可见"** (`mShowType = "2"`):仅好友可见 #### 5.2 交互流程 1. 用户点击 `oiv_show`("谁可以看") 2. 显示对话框:`PublishShowTypeDialog` 3. 用户选择可见范围: - 点击"公开":`mShowType = "1"`, `oiv_show.setDesc("公开")` - 点击"仅好友可见":`mShowType = "2"`, `oiv_show.setDesc("仅好友可见")` 4. 关闭对话框 --- ### 6. 七牛云Token获取 (`getQnToken()`) ```java AppService.Instance().getQnToken(new SimpleCallback() { @Override public void onUiSuccess(GetQnTokenResult getQnTokenResult) { GetQnTokenResult data = getQnTokenResult.getData(); mQnToken = data.getToken(); // 保存Token,用于后续图片上传 } @Override public void onUiFailure(int code, String msg) { // Token获取失败(不影响页面显示,但图片无法上传) } }); ``` **说明**: - Token在页面初始化时获取(`afterViews()`) - Token用于七牛云图片上传认证 - 如果Token获取失败,图片上传功能将无法使用 --- ## 🔄 完整业务流程 ``` 用户打开PublishActivity ↓ 初始化UI(输入框、图片列表、可见范围) ↓ 获取七牛云Token(getQnToken) ↓ 用户输入文字内容(可选) ↓ 用户选择图片(拍照/相册) ↓ 图片压缩(Luban) ↓ 上传图片到七牛云(QiniuUploadFile) ↓ 图片URL添加到列表(arrayListPhoto) ↓ 用户点击"发布"按钮 ↓ 验证内容(文字或图片至少有一个) ↓ 收集数据(content、images、ispravite) ↓ 调用发布接口(AppService.publishContent) ↓ 发布成功 → 关闭页面 发布失败 → 显示错误信息 ``` --- ## 📊 数据结构 ### 发布请求参数 ```java HashMap { "content": "文字内容", // 可选,文字内容 "images": "url1,url2,url3", // 可选,图片URL列表(逗号分隔) "ispravite": "1", // 必填,可见范围(1:公开, 2:仅好友可见) "province": "省份", // 可选,省份(从定位或用户设置获取) "city": "城市", // 可选,城市(从定位或用户设置获取) "district": "区县", // 可选,区县(从定位或用户设置获取) "lat": "纬度", // 可选,纬度(从定位获取) "lng": "经度", // 可选,经度(从定位获取) "poi": "地点" // 可选,地点/详细地址(从定位获取) } ``` ### 图片实体 ```java PhotoInfoEntity { String url; // 图片完整URL(从七牛云获取) String minUrl; // 图片缩略图URL(当前使用相同URL) } ``` --- ## 🛠️ 技术要点 ### 1. 图片选择 - **库**:`PictureSelector` - 强大的图片选择库 - **功能**:支持拍照、相册选择、多选等 ### 2. 图片压缩 - **库**:`Luban` - 图片压缩库 - **目的**:减小图片文件大小,提高上传速度 ### 3. 图片上传 - **云存储**:七牛云(Qiniu) - **流程**:本地文件 → 压缩 → 上传到七牛云 → 获取URL ### 4. RecyclerView适配器 - **适配器**:`FunctionBackImageAdapter` - **布局管理器**:`FunctionBackGridLayoutManager`(自定义,支持3列网格布局) --- ## ⚠️ 注意事项 1. **内容验证**:文字和图片至少需要有一个,否则不允许发布 2. **Token获取**:必须在图片上传前获取Token,否则上传会失败 3. **图片数量限制**:最多选择9张图片 4. **可见范围**:默认为"公开"(`mShowType = "1"`),用户可手动修改为"仅好友可见" 5. **图片上传异步**:图片选择后立即开始压缩和上传,上传成功后自动添加到列表 --- ## 🔍 相关文件 - **布局文件**:`uikit/src/main/res/layout/activity_publish.xml` - **网络服务**:`AppService.publishContent()` - 发布接口 - **网络服务**:`AppService.getQnToken()` - 获取七牛云Token - **图片上传**:`QiniuUploadFile.uploadFile()` - 七牛云上传方法 - **适配器**:`FunctionBackImageAdapter` - 图片列表适配器 --- ## 📝 代码关键位置 ### 发布按钮点击(第96-134行) ```java setToolbarSave("发布", new View.OnClickListener() { // 收集数据并提交发布请求 }); ``` ### 图片选择回调(第204-369行) ```java private FunctionBackImageAdapter.onAddPicClickListener onAddPicClickListener = new ... { // 处理图片选择、压缩、上传逻辑 }; ``` ### 可见范围设置(第143-162行) ```java findViewById(R.id.oiv_show).setOnClickListener(view -> { // 显示可见范围选择对话框 }); ```