372 lines
12 KiB
Plaintext
372 lines
12 KiB
Plaintext
# 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<String, String> headMaps = new HashMap<>();
|
||
|
||
// 1. 添加文字内容
|
||
headMaps.put("content", content);
|
||
|
||
// 2. 添加可见范围(1:公开, 2:仅好友可见)
|
||
headMaps.put("ispravite", mShowType);
|
||
|
||
// 3. 添加图片URL列表(逗号分隔)
|
||
if(adapter != null) {
|
||
List<PhotoInfoEntity> 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<GetQnTokenResult>() {
|
||
@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<String, String> {
|
||
"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 -> {
|
||
// 显示可见范围选择对话框
|
||
});
|
||
```
|
||
|