我有可组合的
fun ShowProduct(name: String, image: String, onDismissed: () -> Unit) {
var state = rememberDismissState();
if (state.isDismissed(DismissDirection.EndToStart)) {
onDismissed()
}
SwipeToDismiss(
state = state,
background = { ShowSwipableActions(name) },
modifier = Modifier
.padding(10.dp, 10.dp)
.height(75.dp),
directions = setOf(DismissDirection.EndToStart),
dismissThresholds = { _ -> FractionalThreshold(0.5f) }
) {
/* Content */
}
}
就像这样
第一次
视图模型:
class ProductsListViewModel() : ViewModel() {
private var _products = mutableStateListOf<Product>()
val products: List<Product>
get() = _products
var isLoadingProducts = mutableStateOf(false);
fun removeProduct(id: String) {
_products.removeIf { x -> x.id == id }
}
fun refresh() {
isLoadingProducts.value = true
if(_products.any()){
_products.clear()
}
for (i in 0..50) {
_products.add(
Product(
i.toString(),
"Product $i",
"*image url*"
)
);
}
isLoadingProducts.value = false
}
}
如果我在ViewModel中删除一个项,然后调用refresh()函数,被删除的键将显示为已删除状态。如果我删除和添加同一项,是否应该在LazyColumn的整个生命周期中使用完全唯一的键?
比如说
i.toString() + System.currentTimeMillis()
1条答案
按热度按时间nwwlzxa71#
由于你发布的代码不完整,我只是假设了其中的一些部分,当我填充缺失的部分时,我只创建了
2
项而不是50
,因为我无法区分我创建的每个红色Box
项。基于显示正在执行的操作的GIF。在滑动删除2个项目并单击“刷新”按钮后,它崩溃并显示以下堆栈跟踪。问题是从这里来的
似乎当您清除
SnapshotStateList
并添加另一组项时,在添加first
项且LazyColumn
执行了更新的那一刻,onDismissed()
被调用,它也会立即调用ViewModel中的remove
函数,并返回先前的状态,它总是引用最后一个被删除的项。我得到的索引1超出界限,当大小为3时,我得到的索引2超出界限,依此类推。一开始看起来可能很奇怪,因为每个人都可能认为当
ShowList
重新组合时,rememberDismissState
会创建一个新的状态,但如果你稍微挖掘一下,你会看到它的API是rememberSaveable{…}
和AFAIK,它在重新组合后仍然存在。修复我的遇到的问题,只是创建一个
remembered{..}
DismissState
。(注意,我不确定这样做是否会有任何其他影响,除了不能生存的配置更改,如屏幕旋转,但它解决了我遇到的崩溃,也可能解决你的)我所做的另一件事是(不是修复,但可能是优化)将dismissState函数调用 Package 在
derivedStateOf
中,因为不这样做(像您的)将在其封闭的可组合函数上执行多次重新组合这些是您修改的组件(您发布的所有代码)。
都是这样用的
输出:(gif没有显示崩溃,但如果使用
rememberDismissState
,单击按钮后会崩溃)注意:我所做的一切都是为了修复我遇到的
crash
问题,但由于我使用的是你的代码,我只是填补了缺失的部分,也许它会解决你的问题。