如果您不知道debounce是什么,它是一种模式设计,目的是避免短暂的误像。
最值得注意的示例是配方剂,可以在母蝙蝠轴上执行意外行为,例如单击按钮以进行注册,身份验证£o等并导致错误!
使用Deboud,我们可以轻松避免这些行为!现在我们已经进行了介绍,让我们去实施。
tl; dr
本文的目的是在任务应用中达到以下结果:
即使母亲betiples点击,也只能创建一个任务。如果您的目标只是查看代码的样本,我们将从活动开始:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
PlaygroundTheme {
Surface(
Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background,
) {
val viewModel by viewModels<TasksListViewModel>()
val uiState by viewModel.uiState.collectAsState()
TasksListScreen(
uiState = uiState,
onCreateClick = {
viewModel.create()
})
}
}
}
}
}
因此,模型,UI状态和ViewModel的模型:
data class Task(
val title: "String"
)
data class TasksListUiState(
val title: "String = \"\","
val onTitleChange: (String) -> Unit = {},
val tasks: List<Task> = emptyList()
)
class TasksListViewModel : ViewModel() {
private val _uiState = MutableStateFlow(TasksListUiState())
val uiState = _uiState.asStateFlow()
private var job: Job = Job()
init {
_uiState.update { currentState ->
currentState.copy(
onTitleChange = {
_uiState.value = _uiState.value.copy(
title = it
)
}
)
}
}
fun create() {
job.cancel()
job = viewModelScope.launch {
delay(3000)
_uiState.update { currentState ->
currentState.copy(
tasks = _uiState.value.tasks +
Task(title = _uiState.value.title)
)
}
}
}
}
和屏幕的筛选:
@Composable
fun TasksListScreen(
uiState: TasksListUiState,
onCreateClick: () -> Unit = {}
) {
val tasks = uiState.tasks
Column {
TextField(
value = uiState.title,
onValueChange = uiState.onTitleChange,
Modifier
.padding(8.dp)
.fillMaxWidth(),
placeholder = {
Text("New task...")
}
)
Button(
onClick = onCreateClick,
Modifier
.padding(8.dp)
.fillMaxWidth()
) {
Text(text = "Create task")
}
if (tasks.isEmpty()) {
Box(modifier = Modifier.fillMaxSize()) {
Text(
text = "No tasks...",
Modifier.align(Alignment.Center),
fontSize = 18.sp,
style = TextStyle.Default.copy(
color = Color.Gray.copy(alpha = 0.5f)
)
)
}
} else {
LazyColumn(
contentPadding = PaddingValues(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
items(tasks) { task ->
Box(
Modifier
.clip(RoundedCornerShape(20.dp))
.border(
1.dp,
color = Color.Gray.copy(
alpha = 0.5f
),
RoundedCornerShape(20.dp)
)
.padding(8.dp)
.fillMaxWidth()
) {
Text(text = task.title)
}
}
}
}
}
}
现在,如果您的强度是要了解道路的动机,请继续阅读文章ð
Kotlin Coroutines实施审问
首先,重要的是要知道我将考虑为Kotlin中的异步委员会提供支持的Coroutine库。
这是几个Kotlin计数中非常常见的工具,还提供了促进Deboud实施的资源。
文章的示例应用程序
举例来说,我将使用带有JetPack Compiss的应用程序来模拟与享受的互动,这是一个任务创建者:
要使您达到相同的结果,请遵循以下实现:
- 屏幕代码:
@Composable
fun TasksListScreen(
uiState: TasksListUiState,
onCreateClick: () -> Unit = {}
) {
val tasks = uiState.tasks
Column {
TextField(
value = uiState.title,
onValueChange = uiState.onTitleChange,
Modifier
.padding(8.dp)
.fillMaxWidth(),
placeholder = {
Text("New task...")
}
)
Button(
onClick = onCreateClick,
Modifier
.padding(8.dp)
.fillMaxWidth()
) {
Text(text = "Create task")
}
if (tasks.isEmpty()) {
Box(modifier = Modifier.fillMaxSize()) {
Text(
text = "No tasks...",
Modifier.align(Alignment.Center),
fontSize = 18.sp,
style = TextStyle.Default.copy(
color = Color.Gray.copy(alpha = 0.5f)
)
)
}
} else {
LazyColumn(
contentPadding = PaddingValues(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
items(tasks) { task ->
Box(
Modifier
.clip(RoundedCornerShape(20.dp))
.border(
1.dp,
color = Color.Gray.copy(
alpha = 0.5f
),
RoundedCornerShape(20.dp)
)
.padding(8.dp)
.fillMaxWidth()
) {
Text(text = task.title)
}
}
}
}
}
}
- emellima£o do Modelo,UI状态E ViewModel:
data class Task(
val title: String
)
data class TasksListUiState(
val title: String = "",
val onTitleChange: (String) -> Unit = {},
val tasks: List<Task> = emptyList()
)
class TasksListViewModel : ViewModel() {
private val _uiState = MutableStateFlow(TasksListUiState())
val uiState = _uiState.asStateFlow()
init {
_uiState.update { currentState ->
currentState.copy(
onTitleChange = {
_uiState.value = _uiState.value.copy(
title = it
)
}
)
}
}
fun create() {
_uiState.update { currentState ->
currentState.copy(
tasks = _uiState.value.tasks +
Task(title = _uiState.value.title)
)
}
}
}
- 创建ViewModel,使用UI状态并调用屏幕的活动代码:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
PlaygroundTheme {
Surface(
Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background,
) {
val viewModel by viewModels<TasksListViewModel>()
val uiState by viewModel.uiState.collectAsState()
TasksListScreen(
uiState = uiState,
onCreateClick = {
viewModel.create()
})
}
}
}
}
}
使用ViewModel和UI状态的国家管理实施。现在我们知道了方式,我们可以按照下一步的方式介绍使该解决方案成为问题的常见场景。
延迟应用程序中的问题情况
最常见的情况是何时创建任务,例如试图发送到API。我们可以使用Coroutines从延迟进行此模拟:suspend fun create() {
delay(3000)
_uiState.update { currentState ->
currentState.copy(
tasks = _uiState.value.tasks +
Task(title = _uiState.value.title)
)
}
}
请注意,这是3秒的延迟!在屏幕的屏幕上,我们需要使用coroutine调用悬浮函数:
...
val scope = rememberCoroutineScope()
TasksListScreen(
uiState = uiState,
onCreateClick = {
scope.launch {
viewModel.create()
}
})
入口,我们可以测试应用程序并在尝试创建任务时多次单击:
看到几秒钟后,任务将出现!为了避免这种情况,我们可以进行访问ð
通过Coroutine Job实施调试
基于Coroutines的审问的实现由koude0的改进控制,因此我们可以将此参考作为ViewModel的属性创建,我们可以应用一些配置:
class TasksListViewModel : ViewModel() {
private var job: Job = Job()
...
fun create() {
job.cancel()
job = viewModelScope.launch {
delay(3000)
_uiState.update { currentState ->
currentState.copy(
tasks = _uiState.value.tasks +
Task(title = _uiState.value.title)
)
}
}
}
}
此实现似乎很复杂,但比看起来要简单!让我们了解每个步骤:
- 我们为
ViewModel
创建了一个可变的Job
2 - 尝试创建任务时,我们取消了取消与其链接的所有coroutines的
job
。 - 运行Coroutine时,我们从Koud5的返回中重新激活
Job
- 启动的
Job
链接到创建新任务的Coroutine - 再次运行并使用新值取消
job
时,以前的Coroutine被取消,并且在相同的循环下创建了一个新值。
看到,如果在3秒的时间内未取消此情况,则该案例将运行!该实现的另一个有趣的细节是,谁称为ViewModel创建的母亲,不需要使用Coroutine!
现在仅创建一个任务!即使它们是徒劳的点击ð
了解更多
botans的辩论是用例,但也可以在其他情况下应用!例如,尝试从邮政编码自动填充地址字段时:
请参阅您停止编写邮政编码后的一段时间之后。该技术很有趣,因为它避免了不必要的设备资源消费,例如处理,互联网等。
该样本是Jetpack Compose: comunicação com REST API课程中建议的挑战的实施,该尝试如何?
如果您不是Alura的订阅者并感兴趣,我可以为您提供此cupom de descontoð
您如何看待与Coroutine一起审问?您使用另一种方法吗?喜欢分享评论。