Как мы можем повысить производительность TextView, когда используется большое количество ImageSpan? - PullRequest
0 голосов
/ 26 мая 2020

Я показал изображения в TextView с помощью ImageSpan и загрузил их в RecyclerView . Прежде всего, я сопоставил шаблон регулярного выражения в тексте и применил Imagespan к этим сопоставленным позициям. Я реализовал Glide , чтобы изображение можно было рисовать с сервера.

fun stringToImage(string:String,imageSize:Int,callback:JoyPixelCallback ) {
    val ssb = SpannableStringBuilder(string)
    val matcher = joypixelEmojiMatcher(string)
    val joyPixelMatcherRangeList = ArrayList<JoyPixelMatcherRange>()
    while (matcher.find()) {
        joyPixelMatcherRangeList.add(JoyPixelMatcherRange(
                mappingString = matcher.group(0) ?: "",
                startIndex = matcher.start(),
                endIndex = matcher.end()
        ))
    }
    if (joyPixelMatcherRangeList.size == 0) {
        callback.onSuccess(ssb)
    }
    replaceShortNameWithImages(ssb, imageSize, matchList, callback);
}

private fun replaceShortNameWithImages(ssb: SpannableStringBuilder, imageSize: Int, matchList: ArrayList<JoyPixelMatcherRange>,
                                       callback: JoyPixelCallback) {
    if (matchList.size == 0) {
        callback.onSuccess(ssb)
    } else {
        try {
            val shortName = matchList[0].mappingString
            val start = matchList[0].startIndex
            val end = matchList[0].endIndex
            matchList.removeAt(0)
            val cleanName = shortName.removePrefix("(:").removeSuffix(":)")
            val emoji = cleanName.removeRange(0, cleanName.indexOf(":") + 1)
            val categoryName = cleanName.substring(0, cleanName.indexOf(":"))
            val url = "https://joypixel.s3-ap-southeast-2.amazonaws.com/emojis/$categoryName/$emoji.png"
            if (url.contains(AppContracts.FileType.IMAGE_PNG)) {
                Glide.with(context)
                        .asDrawable()
                        .diskCacheStrategy(DiskCacheStrategy.DATA)
                        .load(url)
                        .into(object : CustomTarget<Drawable>(imageSize, imageSize) {
                            override fun onResourceReady(bmpDrawable: Drawable, transition: Transition<in Drawable>?) {
                                try {
                                    bmpDrawable.setBounds(0, 0, bmpDrawable.intrinsicWidth, bmpDrawable.intrinsicHeight)
                                    ssb.setSpan(ImageSpan(bmpDrawable), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
                                    replaceShortNameWithImages( ssb, imageSize, matchList, callback)
                                } catch (e: Exception) {
                                    Timber.d("Joypixel Message : ${e.localizedMessage}")
                                }
                            }

                            override fun onLoadCleared(placeholder: Drawable?) {}

                            override fun onLoadFailed(errorDrawable: Drawable?) {
                                replaceShortNameWithImages( ssb, imageSize, matchList, callback)
                                super.onLoadFailed(errorDrawable)
                            }
                        })
            } 
        } catch (e: Exception) {
            e.printStackTrace()
            callback.onSuccess(ssb)
        }
    }
}

Благодаря этому процессу рендеринг текста происходит очень медленно, а также наблюдается задержка при прокрутке. Однако, если я заменю совпадающий текст одним символом, производительность будет нормальной.

override fun onResourceReady(bmpDrawable: Drawable, transition: Transition<in Drawable>?) {
                                try {
                                    val startIndex: Int = ssb.toString().indexOf(shortName)
                                    bmpDrawable.setBounds(0, 0, bmpDrawable.intrinsicWidth, bmpDrawable.intrinsicHeight)
                                    ssb.replace(startIndex, startIndex + shortName.length, ".")
                                    ssb.setSpan(ImageSpan(bmpDrawable), startIndex, startIndex + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
                                    replaceShortNameWithImages( ssb, imageSize, matchList, callback)
                                } catch (e: Exception) {
                                    Timber.d("Joypixel Message : ${e.localizedMessage}")
                                }
                            }

Я пробовал использовать * preComputedText , но проблема все еще существует. Примечание: мне нужно повысить производительность без замены совпадающего текста одним символом.

...