Closed wwy863399246 closed 2 years ago
无法看出问题所在, 你可以fork仓库在sample中复现问题吗?
当前页面树形目录页,用navigation跳转到下一界面返回时,重新设置数据时,展开的子列表会重复出现,折叠的不会
你是不是给itemSublist重复赋值
没有使用itemSublist,只在解析时用到,设置数据只用到 pmRv.bindingAdapter.models = list.onEach { book -> book.itemExpand = true }
@Serializable
data class BookDataModel(
@SerialName("chapterName") val chapterName: String,
@SerialName("chapterCode") val chapterCode: String,
@SerialName("level") val level: Int,
@SerialName("isChecked") var isChecked: Boolean = false,
@SerialName("belongBook") val belongBook: Int,
@SerialName("bookName") var bookName: String = "",
@SerialName("hasChild") val hasChild: Boolean,
@SerialName("report_record") val reportRecord: Int = 0,
@SerialName("mistake_count") val mistakeCount: Int = 0,
@SerialName("upload_status") val uploadStatus: Int = 0,
@SerialName("mistake_list") val mistakeList: List
// 这种代理方式是为了避免Gson等框架解析Kotlin会覆盖默认值问题: https://liangjingkanji.github.io/BRV/group.html#_2
override var itemSublist: List<Any?>?
get() = children
set(value) {
children = value as List<BookDataModel>
}
override var itemHover: Boolean = true
override var itemPosition: Int = 0
}
那你早点fork仓库复现问题吧, 这样解决问题速度快的多
而且sample也正是使用的navigation实现的
另外你不觉得你的网络请求稍显复杂和冗余吗? 而且你这完全无法支持并发请求吧, 推荐你使用Net
我就是用的net,但是得做数据恢复,所以请求写在viewmodel里面,仓库没拉下来,拉下来后试试能不能复现吧,我现在用 pmRv.setDifferModels(list)可以解决这个问题,只是得加个判断
快复现, 我不允许有问题遗留到第二天
数据恢复你把请求回来的数据赋值给ViewModel对象里面的某个字段不就好了吗? 然后判断下对象是否为空, 空则重新请求
为什么还得写liveData观察者?
用LiveData是因为我创建了网络请求状态类,用来设置界面状态,我现在遇到的问题是因为保存的数据变了,我这边是无线层级,第一次请求用上面的模型解析后,拿到的是所有的父条目,假如是5条。列表设置全部展开后,跳转页面回来后我保存的数据条目变成了父条目加上子条目的数量。
无限层级解析,是因为我解析类写的有问题吗?我用你的demo里面的假数据做数据恢复没有问题
启用分组后models会变成父条目+子条目的, 这是无可避免的
另外我极度不推荐使用LiveData去接收网络请求结果, 你这是本末倒置, 依然使用的是接口回调去处理异步任务, 页面关闭应当真正取消网络请求而不是仅仅不监听请求结果
而且网络错误应当抛出异常交由全局异常处理器去处理(比如收集到服务器)而不是设置一个错误状态, 你整个应用的网络请求都有问题
@HiltViewModel class ReportMistakePublishViewModel @Inject constructor() : BaseViewModel() {
private val _catalogueDataState =
MutableLiveData<StateModel<List<BookDataModel>>>()
val catalogueDataState: LiveData<StateModel<List<BookDataModel>>>
get() = _catalogueDataState
fun getBookCatalogue(classId: Int, bookId: Int) = scopeNetLife {
_catalogueDataState.value = StateModel(showLoading = true)
appToken?.let {
val data = Get<Book>("teacher/class/wrong/question/catalogue/info") {
param("token", it)
param("class_id", classId)
param("book_id", bookId)
}.await()
_catalogueDataState.value = StateModel(successData = data.mistakeCatalogue)
}
}.catch {
_catalogueDataState.value = StateModel(showError = it.message ?: "")
}
val mistake = ObservableInt(0)
val section = ObservableInt(0)
} 这是我的viewmodel类 我需要设置界面状态,应该怎样处理才好。
我现在用的是单Activity多fragment,Navigation导航,需要处理界面状态恢复,所以得使用viewmodel。为了不重复请求网络并且设置正确设置界面状态,所以写在viewmodel里面
单Activity.... 你挺会折腾的, 你不会还是什么MVI架构吧
写代码已经够难了, 你还强行给自己加料增加难度
Net支持在ViewModel里面网络请求并且监听ViewModel生命周期, 我建议你将Post
等方法写到ViewModel但是scope**
还是写到Activity中, 他们可以监听生命周期
好的,我现在写的MVVM接近MVI吧,单向数据流动。目前用Net和BRV没啥问题,就是Net的Catch作用域里面不能用flow发送值,所以用livedata发送状态,单Activity很难受,复杂点的fragement页面要保存很多状态。
所以我一直极度不推荐使用SingleActivity
的写法, 遇到的坑非常多, 很多框架你甚至不支持, 而且你需要考虑的东西太多了
而你收获到什么优势? 页面速度快? 你感受到了多少?
只推荐简单的MVVM设计模式, 数据和UI的双向绑定的确优势明显, 代码量少数据安全. 可能有人觉得MVVM太简单了不够卷所以发明了MVI
无论是插件化/组件化/MVI亦或是滥用ViewModel/LiveData我都建议看清楚技术本质, 而不是人云亦云或者套模板
如果页面不需要数据恢复完全不需要使用ViewModel
网络请求属于单次数据流完全不适用Flow, 如果需求是对数据进行数据流处理完全可以使用自带的集合stream扩展函数
不是把代码挪个位置就是优化
你可以看下BRV使用MVVM实现一个聊天列表有多简单直接
确实,前期坑真的很多,都快被我踩完了,我现在简单的页面只要不做数据恢复,用BRV和Net还有databing开发挺爽的。
你解决数据问题了吗? 是models包含子条目的问题是吧
问题描述
返回页面,用pmRv.setDifferModels(list) 恢复树形列表数据,不会出现这个问题
期望行为
如何复现
建议步骤:
截图
异常堆栈信息或者手机截图/视频
版本