多段长文本加载致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
相关产品推荐
相关产品推荐

