Revert emoji cache to old pattern.

This commit is contained in:
Alex Hart
2021-05-06 18:47:36 -03:00
committed by GitHub
parent cb9ab61b6b
commit 138f9476ac
4 changed files with 93 additions and 103 deletions

View File

@@ -1,85 +1,17 @@
package org.thoughtcrime.securesms.emoji
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.Key
import com.bumptech.glide.load.Option
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import org.thoughtcrime.securesms.mms.PartAuthority
import java.io.InputStream
import java.security.MessageDigest
typealias EmojiPageFactory = (Uri) -> EmojiPage
sealed class EmojiPage(private val uri: Uri) : Key {
sealed class EmojiPage(open val uri: Uri) : Key {
override fun updateDiskCacheKey(messageDigest: MessageDigest) {
messageDigest.update("EmojiPage".encodeToByteArray())
messageDigest.update(uri.toString().encodeToByteArray())
}
data class Asset(private val uri: Uri) : EmojiPage(uri)
data class Disk(private val uri: Uri) : EmojiPage(uri)
class Loader(private val context: Context) : ModelLoader<EmojiPage, Bitmap> {
override fun buildLoadData(
model: EmojiPage,
width: Int,
height: Int,
options: Options
): ModelLoader.LoadData<Bitmap> {
return ModelLoader.LoadData(model, Fetcher(context, model, options.get(IN_SAMPLE_SIZE) ?: 1))
}
override fun handles(model: EmojiPage): Boolean = true
class Factory(private val context: Context) : ModelLoaderFactory<EmojiPage, Bitmap> {
override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<EmojiPage, Bitmap> {
return Loader(context)
}
override fun teardown() = Unit
}
}
class Fetcher(private val context: Context, private val model: EmojiPage, private val inSampleSize: Int) : DataFetcher<Bitmap> {
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in Bitmap>) {
try {
val inputStream: InputStream = when (model) {
is Asset -> context.assets.open(model.uri.toString().replace("file:///android_asset/", ""))
is Disk -> EmojiFiles.openForReading(context, PartAuthority.getEmojiFilename(model.uri))
}
val bitmapOptions = BitmapFactory.Options()
bitmapOptions.inSampleSize = inSampleSize
callback.onDataReady(BitmapFactory.decodeStream(inputStream, null, bitmapOptions))
} catch (e: Exception) {
callback.onLoadFailed(e)
}
}
override fun cleanup() = Unit
override fun cancel() = Unit
override fun getDataClass(): Class<Bitmap> {
return Bitmap::class.java
}
override fun getDataSource(): DataSource {
return DataSource.LOCAL
}
}
companion object {
@JvmField
val IN_SAMPLE_SIZE: Option<Int> = Option.memory("emoji_page_in_sample_size", 1)
}
data class Asset(override val uri: Uri) : EmojiPage(uri)
data class Disk(override val uri: Uri) : EmojiPage(uri)
}

View File

@@ -0,0 +1,73 @@
package org.thoughtcrime.securesms.emoji
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import androidx.annotation.MainThread
import androidx.annotation.WorkerThread
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.mms.PartAuthority
import org.thoughtcrime.securesms.util.ListenableFutureTask
import org.thoughtcrime.securesms.util.SoftHashMap
import org.thoughtcrime.securesms.util.concurrent.SimpleTask
import java.io.IOException
import java.io.InputStream
object EmojiPageCache {
private val TAG = Log.tag(EmojiPageCache::class.java)
private val cache: SoftHashMap<EmojiPageRequest, Bitmap> = SoftHashMap()
private val tasks: HashMap<EmojiPageRequest, ListenableFutureTask<Bitmap>> = hashMapOf()
@MainThread
fun load(context: Context, emojiPage: EmojiPage, inSampleSize: Int): ListenableFutureTask<Bitmap> {
val applicationContext = context.applicationContext
val emojiPageRequest = EmojiPageRequest(emojiPage, inSampleSize)
val bitmap: Bitmap? = cache[emojiPageRequest]
val task: ListenableFutureTask<Bitmap>? = tasks[emojiPageRequest]
return when {
bitmap != null -> ListenableFutureTask(bitmap)
task != null -> task
else -> {
val newTask = ListenableFutureTask<Bitmap> {
try {
Log.i(TAG, "Loading page $emojiPageRequest")
loadInternal(applicationContext, emojiPageRequest)
} catch (e: IOException) {
Log.w(TAG, e)
null
}
}
tasks[emojiPageRequest] = newTask
SimpleTask.run(newTask::run) {
try {
cache[emojiPageRequest] = newTask.get()
} finally {
tasks.remove(emojiPageRequest)
}
}
newTask
}
}
}
@WorkerThread
private fun loadInternal(context: Context, emojiPageRequest: EmojiPageRequest): Bitmap? {
val inputStream: InputStream = when (emojiPageRequest.emojiPage) {
is EmojiPage.Asset -> context.assets.open(emojiPageRequest.emojiPage.uri.toString().replace("file:///android_asset/", ""))
is EmojiPage.Disk -> EmojiFiles.openForReading(context, PartAuthority.getEmojiFilename(emojiPageRequest.emojiPage.uri))
}
val bitmapOptions = BitmapFactory.Options()
bitmapOptions.inSampleSize = emojiPageRequest.inSampleSize
return BitmapFactory.decodeStream(inputStream, null, bitmapOptions)
}
private data class EmojiPageRequest(val emojiPage: EmojiPage, val inSampleSize: Int)
}