You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多段长文本加载致Activity启动卡顿,求标准解决方案

解决JustifiedTextView批量加载长文本导致启动卡顿的标准方案

这个问题我之前做图文排版类应用时踩过坑,本质是主线程被密集的文本排版计算阻塞了——8个长文本的两端对齐计算全在启动时同步执行,直接把主线程的UI渲染队列堵死,自然会出现界面迟迟不显示的卡顿。下面是几个业界通用的解决思路,亲测有效:

1. 将文本排版计算移到子线程

JustifiedTextView的核心工作是对文本进行两端对齐的排版计算,这是典型的CPU密集型操作,完全可以放到后台线程完成,计算好成品后再切回主线程设置文本。用Kotlin Coroutines或者Java的ExecutorService都可以,这里给个Coroutines的示例:

// 在Activity/Fragment的onCreate或onViewCreated里执行
lifecycleScope.launch(Dispatchers.IO) {
    // 批量处理所有长文本的排版
    val processedTexts = listOf(
        R.string.long_text_1, R.string.long_text_2,
        R.string.long_text_3, R.string.long_text_4,
        R.string.long_text_5, R.string.long_text_6,
        R.string.long_text_7, R.string.long_text_8
    ).map { resId ->
        val rawText = requireContext().getString(resId)
        // 替换成你用的JustifiedTextView库的排版方法
        // 比如有些库会返回Spanned或者处理好的CharSequence
        YourJustifiedTextViewUtils.processJustifiedText(rawText)
    }

    // 切回主线程更新UI
    withContext(Dispatchers.Main) {
        textView1.text = processedTexts[0]
        textView2.text = processedTexts[1]
        textView3.text = processedTexts[2]
        textView4.text = processedTexts[3]
        textView5.text = processedTexts[4]
        textView6.text = processedTexts[5]
        textView7.text = processedTexts[6]
        textView8.text = processedTexts[7]
    }
}

2. 分批次/懒加载非可见区域的文本

如果这8个TextView是在可滚动布局(比如ScrollView、RecyclerView)中,很多在启动时其实是不可见的,完全不用一次性加载。

  • 如果是RecyclerView:直接在onBindViewHolder里才触发当前Item的文本排版,只给可见的Item加载内容。
  • 如果是线性布局/相对布局:用分批次延迟加载的方式,分散主线程压力,比如每100ms加载2个:
val textViews = listOf(textView1, textView2, ..., textView8)
val stringIds = listOf(R.string.long_text_1, ..., R.string.long_text_8)
val handler = Handler(Looper.getMainLooper())

// 按2个一组分批次加载
textViews.chunked(2).forEachIndexed { batchIndex, batchViews ->
    val batchStrings = stringIds.chunked(2)[batchIndex]
    handler.postDelayed({
        batchViews.forEachIndexed { index, tv ->
            val rawText = getString(batchStrings[index])
            tv.text = YourJustifiedTextViewUtils.processJustifiedText(rawText)
        }
    }, batchIndex * 100L) // 每批间隔100ms
}

3. 缓存排版后的文本结果

如果这些长文本是固定不变的,完全可以把排版后的结果缓存起来,避免每次启动都重复计算。用LruCache做内存缓存,或者存到SharedPreferences/本地文件做持久化缓存:

// 初始化内存缓存,最多存8个文本结果
private val textCache = LruCache<String, CharSequence>(8)

private fun getCachedJustifiedText(resId: Int): CharSequence {
    val cacheKey = "text_$resId"
    var cachedText = textCache.get(cacheKey)
    if (cachedText == null) {
        val rawText = getString(resId)
        cachedText = YourJustifiedTextViewUtils.processJustifiedText(rawText)
        textCache.put(cacheKey, cachedText)
    }
    return cachedText
}

// 使用时直接取缓存
textView1.text = getCachedJustifiedText(R.string.long_text_1)

4. 优化JustifiedTextView的排版效率

有些第三方JustifiedTextView库的算法效率不高,比如每次setText都会重新全量计算,或者在onMeasure里做大量逻辑。可以:

  • 给TextView设置固定宽高(如果布局允许),避免多次measure;
  • 检查库是否有异步排版的API,优先使用官方提供的异步方法;
  • 开启硬件加速(在Activity的清单文件里设置android:hardwareAccelerated="true"),提升渲染效率。

内容的提问来源于stack exchange,提问作者ShababQaisar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:18:36