Android之流式显示内容

文章目录


前言

相信很多新童鞋刚接触AI产品或者小说产品会遇到一个要求,就是返回的内容需要流式读取,比如生成小说,不会一次性给你返回结果的,你会定时请求接口或者websocket,每次给你返回一些文字,你要把每次的文字给组装起来并流式读取,来看看吧。


一、什么是流式读取?

流式读取,顾名思义像流水似得,慢慢读取,比如给你一篇文章,正常一下就有展示完了,但是有些地方需要流式效果,就需要一个字一个字慢慢读取达到效果。

二、实现步骤

代码如下(示例):

kotlin 复制代码
//定义变量
private var currentLength = 0 // 记录已显示的字符位置
private var animator: ValueAnimator? = null // 用于取消之前的动画
//每次调接口累加文本
for (i in listsj.indices) {
   context += listsj[i]
  }
//调用
animateTextFlow(context)
//实例化
val rotationAnimator = ObjectAnimator.ofFloat(imag_zq, "rotation", 0f, 360f)
    rotationAnimator.setDuration(2000) // 单次旋转时长(毫秒)
    rotationAnimator.repeatCount = ObjectAnimator.INFINITE // 无限循环
    rotationAnimator.interpolator = LinearInterpolator() // 线性匀速旋转
    rotationAnimator.start()
//流式读取方法
private fun animateTextFlow(fullText: String) {
        // 取消之前的动画并立即更新 currentLength
        animator?.cancel()
        animator = null
        currentLength = text_context.text.length // 关键修复点

        val newText = fullText.substring(currentLength)
        if (newText.isEmpty()) return

        val snapshotFullText = fullText
        val snapshotCurrentLength = currentLength

        animator = ValueAnimator.ofInt(0, newText.length).apply {
            duration = newText.length * 50L
            addUpdateListener { animation ->
                val index = animation.animatedValue as Int
                text_context.text = snapshotFullText.substring(0, snapshotCurrentLength + index)
                scrollview.post { scrollview.fullScroll(View.FOCUS_DOWN) }
            }
            addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
                    currentLength = snapshotCurrentLength + newText.length // 确保更新为实际长度
                }

                override fun onAnimationCancel(animation: Animator) {
                    // 动画取消时,更新 currentLength 为当前已显示的字符数
                    currentLength = text_context.text.length
                }
            })
            start()
        }
    }
 override fun onDestroy() {
        super.onDestroy()
        animator?.cancel() // 防止内存泄漏
    }

总结

其实流式读取很简单,需要注意的点就是记录每次读取的位置,不然会读取重复。