当由另一个对象(如TextWatcher)封装时,是否需要对actor或通道进行管理(关闭/终止)?

时间:2018-10-10 18:28:35

标签: android kotlin coroutine kotlinx.coroutines

我想实现一个DebounceTextWatcher。我打算使用actor来消耗文本更改并在指定的时间间隔内反跳,然后将事件转发给外部使用者。代码如下:

class DebounceTextWatcher(
  delayMs: Long = DebounceTextWatcher.DEFAULT_TIMER_DELAY_MS,
  handler: (text: String) -> Unit
) : TextWatcher {

  private val channel = GlobalScope.actor<String> {
    debounce(delayMs).consumeEach(handler)
  }

  override fun afterTextChanged(s: Editable?) {
    channel.offer(s?.toString().orEmpty())
  }

  override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
  override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}

  companion object {
    const val DEFAULT_TIMER_DELAY_MS = 600L
  }
}

fun <T> ReceiveChannel<T>.debounce(timeMs: Long): ReceiveChannel<T> = GlobalScope.produce {
  var value = receive()

  whileSelect {
    onTimeout(timeMs) {
      send(value)
      value = receive()
      true
    }
    onReceive {
      value = it
      true
    }
  }
}

我的担忧是

  1. 这是对GlobalScope的正确使用吗?还是应该将CoroutineContextCoroutineScope作为依赖项传递?
  2. 在保存TextWatcher引用的close() / actor的生命周期结束时,我是否需要担心以任何方式调用Activity或终止Fragment? / li>

我的假设是,根据this的帖子,我不必担心此事,但我想确定一下。

1 个答案:

答案 0 :(得分:2)

通道本身不会保留任何资源,但是您的处理程序可能会保留。您要冒这样的事件顺序:

  1. 一个项目进入了频道的输入队列
  2. 应用程序暂停,其活动被破坏
  3. 应用程序恢复,现在项目已处理
  4. 绑定到旧活动的处理程序运行并导致应用崩溃

在类似的情况下,我有很多虚假的崩溃。我不停地插一个洞,在某些设备和某些特殊情况下,该应用仍然崩溃。仅当我实现“主作业”模式时,它才停止。后来,科特林实施了这种模式。