首页 > 解决方案 > Android Kotlin:完成工作后让视图类通过

问题描述

我想让我的应用程序用打字机效果一一显示文本。我为效果制作了一个自定义视图。当第一个自定义视图完成显示文本时,我的应用程序将等待点击屏幕或布局。单击时,下一个自定义视图开始显示文本,完成后等待单击,依此类推。

这是我制作的自定义视图:

class TypeWriterView: AppCompatTextView {
private var mText: CharSequence? = null
private var mIndex = 0
private var mDelay: Long = 150 // in ms

  constructor(context: Context) : super(context)
  constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

  private val mHandler: Handler = Handler()
  private val characterAdder: Runnable = object : Runnable {
      override fun run() {
          text = mText!!.subSequence(0, mIndex++)
          if (mIndex <= mText!!.length) {
              mHandler.postDelayed(this, mDelay)
          }
      }
  }

  fun commence(txt: CharSequence?, delay: Long) {
    mText = txt
    mIndex = 0
    text = ""
    mDelay = delay
    mHandler.removeCallbacks(characterAdder)
    mHandler.postDelayed(characterAdder, mDelay)
  }
}

为了让它像我上面提到的那样工作,我认为它需要在完成时将一些值传递给活动(在我的情况下它实际上是一个片段),所以我搜索了一些并将一些代码放在 run() 方法中。

override fun run() {
   val job = GlobalScope.launch(Dispatchers.Default) {
       text = mText!!.subSequence(0, mIndex++)
       if (mIndex <= mText!!.length) {
           mHandler.postDelayed(**this**, mDelay)
       }
   }
   runBlocking {
       job.join()
       // pass value after finishing to display texts
   }
}

然后“ this ”得到红色下划线,并显示错误消息:

Type mismatch.
Required: Runnable
Found: CoroutineScope

那么我应该在这里放什么而不是“这个”?或者有没有更好的方法来做到这一点?

标签: androidkotlin

解决方案


Handler您使用协程时,它是没有用的。

应该用来延迟执行,delay()你不需要一次又一次地把 Runnable 推送到线程。

class TypeWriterView: AppCompatTextView {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    suspend fun commence(txt: CharSequence?, delayMs: Long) {
        if (txt == null) return

        var index = 0
        while (index < txt.length) {
            text = txt.subSequence(0, ++index)
            delay(delayMs)
        }
    }

    // Get [Job] reference after launching in [owner]
    fun commenceOnLifecycle(owner: LifecycleOwner, txt: CharSequence?, delayMs: Long): Job =
            owner.lifecycleScope.launch { commence(txt, delayMs) }
}

LifecycleOwner 由 Activity、Fragment 等实现,无论哪个附加了生命周期(更多信息:LifecycleOwner),默认情况下它会将作业调度到 Dispatchers.Main 以便可以更改 UI。


推荐阅读