如何将图像加载到Android的RecyclerView Adapter中



在我的应用程序中,我应该显示图像到recyclerview适配器。
我有两个api
第一个API发送给我图像id,我应该把这个id发送给第二个API getbase64然后解码这个base64位图并再次将其显示为ImageView!
我写了下面的代码,但是每个项目首先发送API,接收base64,解码并显示为ImageView,但当滚动项目显示我滞后

我的适配器代码:

class MyAdapter constructor(private val items: MutableList<Result>) : RecyclerView.Adapter<ViewHolder>() {
private lateinit var binding: ItemBinding
private lateinit var context: Context
private val userToken by lazy { GoodPrefs.getInstance().getString(USER_TOKEN, "") }
private var decodedBytes: ByteArray? = null
@SuppressLint("SimpleDateFormat")
val formatter: DateFormat = SimpleDateFormat("yyyy-MM-dd")
lateinit var date: Date
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
binding = ItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
context = parent.context
return ViewHolder()
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
holder.setIsRecyclable(false)
}
override fun getItemCount(): Int {
return items.size
}
inner class ViewHolder : RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SetTextI18n")
fun bind(item: Result) {
binding.apply {
//Title
titleTxt.text = item.title
//Date
val dateStr = item.publishAt!!.split(" ")[0]
date = formatter.parse(dateStr) as Date
dateTxt.text = timeDiffer(date.time / 1000)
//Like
if (item.youLikeBefore!!) {
likeImg.setImageResource(R.drawable.ic_heart)
likeImg.setColorFilter(ContextCompat.getColor(context, R.color.mystic))
} else {
likeImg.setImageResource(R.drawable.ic_heart_line)
likeImg.setColorFilter(ContextCompat.getColor(context, R.color.black))
}
if (item.likeCount!! > 0) {
likeTxt.isVisible = true
likeTxt.text = item.likeCount.toString()
} else {
likeTxt.isVisible = false
}
//File
if (item.file != null) {
when (item.file.type) {
IMAGE -> {
thumbImg.isVisible = true
thumbLoading.isVisible = true
ApiClient.getInstance().apisUseCase().getAvatarImage(userToken, item.file.id!!)
.applyIoScheduler()
.subscribe({
thumbLoading.isVisible = false
if (it.isSuccessful) {
if (it.code() == 200) {
if (it.body() != null) {
decodedBytes = Base64.decode(it.body()!!.data!!.file, Base64.DEFAULT)
thumbImg.load(decodedBytes) {
memoryCachePolicy(CachePolicy.ENABLED)
}
}
}
}
}, {
thumbLoading.isVisible = false
})
}
VOICE -> {
thumbImg.load(R.drawable.img_voice)
thumbLoading.isVisible = false
}
VIDEO -> {
thumbImg.load(R.drawable.img_video)
thumbLoading.isVisible = false
}
}
}
//User
if (item.user != null) {
doctorNameTxt.text = "${item.user.firstName} ${item.user.lastName}"
}
//Click
likeImg.setOnClickListener {
onItemClickListener?.let {
it(item)
}
}
}
}
}
private var onItemClickListener: ((Result) -> Unit)? = null
fun setOnItemClickListener(listener: (Result) -> Unit) {
onItemClickListener = listener
}
@SuppressLint("NotifyDataSetChanged")
fun addItems(items: MutableList<Result>) {
this.items.addAll(items)
notifyDataSetChanged()
}
}

首先,我有一个问题,这样是真的吗?
我只想调用这个API一次!
在我的代码每个滚动调用API,我使用线圈缓存图像加载器,但再次从服务器获取图像不从缓存调用!

我该如何修复它?

根据谈话,我猜图像解码发生在UI线程中。

如果是这种情况,您可以使用ExecutorsCoroutines

然而,我不是Kotlin开发人员,所以我不熟悉Coroutines的情况。但它与Executors相似,所以我将首先发布Executors的答案。

字节数组准备好后,

执行人的例子:

var uiHandler: Handler = Handler(Looper.getMainLooper())
// Decode your byte array in another thread
fun decodeAndLoad(file: ByteArray?) {
val executor = Executors.newCachedThreadPool()
executor.execute {
val decodedBytes = Base64.decode(file, Base64.DEFAULT)
uiHandler.post {
//TODO: Load your the byte array to image view here
}
}
}

Coroutines case:(Updated)

fun decodeAndLoad(file: ByteArray?) {
val job = GlobalScope.launch(Dispatchers.IO) {
val decodedBytes = Base64.decode(file, Base64.DEFAULT)
withContext(Dispatchers.Main){
//TODO: Load your the byte array to image view here
}
}
}

如果可能的话,我认为你应该使用Glide毕加索和库来加载RV中的图像。只需输入URL和图像加载(即IO线程下载,UI线程加载),缓存将为您完成。

最新更新