RecyclerView使用glide加载图片列表刷新第二次后大小会缩小

测试RecyclerView使用glide加载图片自适应大小的时候发现,第一次是正常的,可是在二次刷新的的时候或者滑动隐藏重新加载出来的时候图片的大小都会变小,甚至三次四次刷新的时候会更小,后面研究解决了一下。

一、先说解决办法。

.解决思路

在第一次加载的时候利用glide的加载监听方法获取保存图片的宽高,在二次以后的加载的时候利用glide的override方法设置该图片的大小。

我是用了一个map来保存的map(url,bean(含有图片宽高属性的bean))

下面给出主要的代码(kotlin的,不过用java的应该也能看懂吧)

1.recyclerview的adapter适配器

package com.zm.androidtest.adapter

import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.util.Log
import android.view.LayoutInflater.from
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.zm.androidtest.R
import com.zm.androidtest.bean.DataBean
import com.zm.androidtest.bean.ImageGlideBean
import kotlinx.android.synthetic.main.layout_recyclerview_item.view.*
import kotlinx.android.synthetic.main.layout_recyclerview_item.view.tv_name
import kotlinx.android.synthetic.main.layout_students_list_item.view.*

/**
 * 可参考 https://www.jianshu.com/p/4357783bd242
 * 或者 https://blog.csdn.net/sinat_35241409/article/details/81871448
 */

class MyRecyclerAdapter (var list:MutableList<DataBean>): RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    var imgMap = HashMap<String,ImageGlideBean>() //用这个map来保存图片的参数,key用url,值设置为一个属性有图片的宽高的变量
    private var itemClickListener: IKotlinItemClickListener? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            val  inflate = from(parent?.context).inflate(R.layout.layout_recyclerview_item, null)
            return MyHolder(inflate)
        
    }

    override fun getItemCount(): Int {
        return list.size
    }

    //listview可参照https://www.jianshu.com/p/4357783bd242
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if(holder is MyHolder){
            holder.bind(list[position])
        }

        // 点击事件
        holder.itemView.setOnClickListener {
            itemClickListener?.onItemClickListener(position)
        }

    }

    override fun getItemViewType(position: Int): Int {
        when(position){
            //多布局
            in 1..2 ->
                return 1
            else -> return super.getItemViewType(position)
        }
    }


    //布局1
  inner  class MyHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        val requestOptions = RequestOptions()
            .error(R.mipmap.ic_book_def)
            .skipMemoryCache(true)
            .diskCacheStrategy(DiskCacheStrategy.NONE)
            .dontAnimate()

         fun bind(date: DataBean){
             itemView.tv_num.text = (adapterPosition+1).toString()+"."
             itemView.tv_name.text=date.name
             //如果保存的imgMap里面没有包含图片的url,就先加载一次,并根据url保存该图片的宽高参数
             if(!imgMap.containsKey(date.imgUrl))
             {
                 Glide.with(itemView.context)
                     .asBitmap()
                     .load(date.imgUrl)
                     .apply(requestOptions)
                     .listener(object :RequestListener<Bitmap>{
                         override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Bitmap>?, isFirstResource: Boolean): Boolean {

                             return false
                         }

                         override fun onResourceReady(resource: Bitmap?, model: Any?, target: Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                             Log.i("image","onResourceReady---图片加载成功----"+(adapterPosition+1)+"---width=="+resource?.width+",height=="+resource?.height+"----url=="+date.imgUrl+"-----imgMap.size="+imgMap.size)
                             if(!imgMap.containsKey(date.imgUrl))
                             {
                                 imgMap.put(date.imgUrl, ImageGlideBean(date.imgUrl,resource?.width!!,resource?.height!!))
                             }
                             return false
                         }

                     })
                     .into(itemView.iv_icon)
             }
             //如果该图片的url已经被保存过了,则根据url取出该图片的宽高指定宽高后加载
             else{
                 Log.i("image","onResourceReady---图片加载成功----"+(adapterPosition+1)+"----url=="+date.imgUrl+"-----imgMap.size="+imgMap.size)
                 Glide.with(itemView.context)
                     .asBitmap()
                     .load(date.imgUrl)
                     .override(imgMap.get(date.imgUrl)?.width!!,imgMap.get(date.imgUrl)?.height!!)
                     .into(itemView.iv_icon)
             }


        }

        var tv_name:TextView = itemView.findViewById(R.id.tv_name)
    }

    // 提供set方法
    fun setOnKotlinItemClickListener(itemClickListener: IKotlinItemClickListener) {
        this.itemClickListener = itemClickListener
    }

    //自定义接口
    interface IKotlinItemClickListener {
        fun onItemClickListener(position: Int)
    }

    //在需要清空的时候调用清空map数据
    fun cleanUrlMap()
    {
        imgMap.clear()
    }

}

2.用来保存在map里面的bean类

data class  ImageGlideBean
 (
    var imgUrl:String,
    var width:Int,
    var height:Int
)

3.列表选项的 layout_recyclerview_item 布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
                android:background="@drawable/recycleview_item_bg"><!--这里有背景改变颜色的知识点-->
    <TextView
            android:id="@+id/tv_num"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="1."
            android:layout_centerVertical="true"
            android:textSize="40px"/>
    <ImageView
            android:id="@+id/iv_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:adjustViewBounds="true"
            android:focusable="false"
            android:scaleType="centerInside"
            android:layout_toRightOf="@id/tv_num"
            android:layout_marginLeft="20px"/>
    <TextView
            android:id="@+id/tv_name"
            android:layout_width="match_parent"
            android:layout_height="250px"
            android:layout_toRightOf="@id/iv_icon"
            android:textSize="20sp"
            android:padding="15dp"
            android:gravity="center_vertical"
            android:layout_marginLeft="10dp"
            android:textColor="#000000"
            android:layout_centerVertical="true"/>

</RelativeLayout>

经过上面的设置不论是重新setAdapter还是adapter?.notifyDataSetChanged()刷新列表的时候图片的大小都不会改变了,这样就解决了该问题了。 为什么会造成这样的结果也是没能探究出来,搞了好久都解决不了,可能是holder里面的什么缓存导致的吧,

下面说一些题外话

因为我们的项目刚开始就是要每次都刷新数据的,所以我刚开始的解决办法就是每次都setAdapter的方式,不过后面有网友提出设置之后列表每次都从头开始了,后面是根据该网友的问题才重新写了个demo去解决他说的问题,最后才重新发现并解决了上面的图片大小变化问题。

在这里也顺便说一下重新setAdapter之后列表重头开始的解决办法

1.定义一个变量distance,用了保存列表滑动的距离

2.给列表设置滑动监听,更新保存滑动距离distance

recyclerview.addOnScrollListener(object :RecyclerView.OnScrollListener(){
    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
        super.onScrollStateChanged(recyclerView, newState)
    }

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy)
        distance += dy
        Log.i("main","recyclerview滑动到的位置dx----="+dx+",dy---="+dy+"----distance="+distance)
    }

})

3.在重新setAdapter之后让列表滚动滑动到该距离即可

recyclerview.smoothScrollBy(0,distance)

不过这样设置刷新之后会有重新滚动的一点效果,说实话有点不太爽,不过好像也不太好解决这个问题,就暂时扩展到这了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值