Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin

这篇具有很好参考价值的文章主要介绍了Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

build.gradle文件:

plugins {
    id("org.jetbrains.kotlin.kapt")
}


implementation("com.github.bumptech.glide:glide:4.16.0")
kapt("com.github.bumptech.glide:compiler:4.16.0")

如果手机图片很多,假设已经将全部图片装入宫格的列表,在快速上下滑动过程中,由于glide会累积每一个图片的加载任务,如果图片比较大,上下滑动时间又很长,那么累积任务会很严重,导致异常发生,实现在RecyclerView切入后台(或不可见)时候,然后再次切换回来,只加载当前RecyclerView可见区域的item,非可见区域的图片加载任务,全部清除掉。

注意这里是利用onRestart生命周期模拟当RecyclerView不可见又切换回来的场景,这里可以换成其他场景,只要捕捉到RecyclerView已经消失在视野可见区域,比如利用fragment或者activity的可见性判断等等。

import android.content.Context
import android.graphics.Bitmap
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatImageView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import java.lang.ref.WeakReference

const val PHOTO_SIZE = 150

const val EMPTY = 0
const val LOAD = 1

class MainActivity : AppCompatActivity() {
    private val TAG = "Glide FLY"

    private var mItems = ArrayList<MyData>()
    private var mLayoutManager: GridLayoutManager? = null
    private var mAdapter: MyAdapter? = null
    private var mVisibleItemPosition: IntArray? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        init()

        mItems = readAllImage(applicationContext)
        mAdapter?.onChange(mItems)
    }

    override fun onResume() {
        super.onResume()
        Log.d(TAG, "onResume")
    }

    //当按了home键后,再次调出app,会进入onRestart
    override fun onRestart() {
        super.onRestart()
        Log.d(TAG, "onRestart")

        loadOnlyVisibleItem()
    }

    private fun loadOnlyVisibleItem() {
        Log.d(TAG, "可见区域 ${mVisibleItemPosition!![0]}->${mVisibleItemPosition!![1]}")
        for (i in mVisibleItemPosition!![0]..mVisibleItemPosition!![1]) {
            Log.d(TAG, "可见区域 ${mItems[i].pos} -- ${mItems[i].path}")
        }

        for (i in 0 until mItems.size) {
            if (i !in mVisibleItemPosition!![0]..mVisibleItemPosition!![1]) {
                if (mItems[i].status == LOAD) {
                    mItems[i].targetRef?.get()?.let {
                        GlideApp.with(this).clear(it)
                    }
                    mItems[i].status = EMPTY
                }
            }
        }
    }

    private fun getVisibleItemPosition(): IntArray {
        val first = mLayoutManager?.findFirstVisibleItemPosition()
        val last = mLayoutManager?.findLastVisibleItemPosition()
        return intArrayOf(first!!, last!!)
    }

    private fun init() {
        val spanCount = 8

        val rv = findViewById<RecyclerView>(R.id.recycler_view)

        mLayoutManager = GridLayoutManager(this, spanCount)
        rv.layoutManager = mLayoutManager

        rv.addOnScrollListener(object : OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                mVisibleItemPosition = getVisibleItemPosition()
            }
        })

        mAdapter = MyAdapter(this)
        rv.adapter = mAdapter
    }

    private fun readAllImage(context: Context): ArrayList<MyData> {
        val photos = ArrayList<MyData>()

        //读取手机图片
        val cursor = context.contentResolver.query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            null,
            null,
            null,
            null
        )

        while (cursor!!.moveToNext()) {
            //图片路径 uri
            val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))

            //图片名称
            //val name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME))

            //图片大小
            //val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE))

            photos.add(MyData(path))
        }

        cursor.close()

        return photos
    }
}

class MyAdapter(private val context: Context) : RecyclerView.Adapter<MyVH>() {
    private var items = ArrayList<MyData>()

    fun onChange(items: ArrayList<MyData>) {
        this.items = items
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {
        val v = LayoutInflater.from(context).inflate(R.layout.item, parent, false)
        val params = v.layoutParams
        params.width = PHOTO_SIZE
        params.height = PHOTO_SIZE
        return MyVH(v)
    }

    override fun onBindViewHolder(holder: MyVH, position: Int) {
        load(holder, position)
        holder.text.text = "$position"
    }

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

    private fun load(holder: MyVH, position: Int) {
        items[position].pos = position
        items[position].status = LOAD

        val target: Target<*> = GlideApp.with(holder.itemView.context)
            .asBitmap()
            .load(items[position].path)
            .centerCrop()
            .addListener(object : RequestListener<Bitmap> {
                override fun onLoadFailed(
                    e: GlideException?,
                    model: Any?,
                    target: Target<Bitmap>,
                    isFirstResource: Boolean
                ): Boolean {
                    items[position].status = EMPTY
                    return false
                }

                override fun onResourceReady(
                    resource: Bitmap,
                    model: Any,
                    target: Target<Bitmap>?,
                    dataSource: DataSource,
                    isFirstResource: Boolean
                ): Boolean {
                    holder.image.setImageBitmap(resource)
                    items[position].status = EMPTY

                    // 特别注意此处返回是true,而不能是false。
                    // 因为如果返回false,当按home键把app切入后台后,再按app图标调出app切换到前台可见,反复切换,
                    // 会造成Bitmap未回收的崩溃。
                    return true
                }
            }).preload(
                PHOTO_SIZE,
                PHOTO_SIZE
            )

        items[position].targetRef = WeakReference(target)
    }
}

class MyVH(itemView: View) : RecyclerView.ViewHolder(itemView) {
    var image: AppCompatImageView
    var text: TextView

    init {
        image = itemView.findViewById(R.id.image)
        text = itemView.findViewById(R.id.text)
    }
}

class MyData(var path: String) {
    var targetRef: WeakReference<Target<*>>? = null
    var status = EMPTY
    var pos = 0
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="1px">

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_launcher_background" />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@android:color/holo_green_light"
        android:paddingLeft="1dp"
        android:paddingRight="1dp"
        android:text="-.-"
        android:textColor="@android:color/holo_red_dark"
        android:textSize="5dp" />
</RelativeLayout>
import android.content.Context
import android.util.Log
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.AppGlideModule

@GlideModule
class MyModule : AppGlideModule() {
    override fun applyOptions(context: Context, builder: GlideBuilder) {
        builder.setLogLevel(Log.DEBUG)
    }

    override fun isManifestParsingEnabled(): Boolean {
        return false
    }
}

Android Glide预加载preload ,kotlin_zhangphil的博客-CSDN博客【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用户的头像是从服务器端读出的一个普通矩形图片,但是现在的设计一般要求在APP端的用户头像显示成圆形头像,那么此时虽然Glide可以加载,但加载出来的是一个矩形,如果要Glide_android 毛玻璃圆角。《Android图片加载与缓存开源框架:Android Glide》Android Glide是一个开源的图片加载和缓存处理的第三方框架。_glide预加载https://blog.csdn.net/zhangphil/article/details/131635804Android Glide预处理preload原始图片到成品resource & 预加载RecyclerViewPreloader,Kotlin_zhangphil的博客-CSDN博客【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用户的头像是从服务器端读出的一个普通矩形图片,但是现在的设计一般要求在APP端的用户头像显示成圆形头像,那么此时虽然Glide可以加载,但加载出来的是一个矩形,如果要Glide_android 毛玻璃圆角。《Android图片加载与缓存开源框架:Android Glide》Android Glide是一个开源的图片加载和缓存处理的第三方框架。https://blog.csdn.net/zhangphil/article/details/132000010

Android Glide自定义AppGlideModule,让Glide在app启动后基于定制化GlideModule加载,kotlin_zhangphil的博客-CSDN博客在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用户的头像是从服务器端读出的一个普通矩形图片,但是现在的设计一般要求在APP端的用户头像显示成圆形头像,那么此时虽然Glide可以加载,但加载出来的是一个矩形,如果要Glide_android 毛玻璃圆角。《Android图片加载与缓存开源框架:Android Glide》Android Glide是一个开源的图片加载和缓存处理的第三方框架。https://blog.csdn.net/zhangphil/article/details/131592226文章来源地址https://www.toymoban.com/news/detail-691301.html

到了这里,关于Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • android 监听app前后台切换

    需求是统计app使用时长,要求在按home键的时候也算一次完成的使用记录。刚开始打算采用监听home键点击,寻求的方法是监听系统广播。 可以实现监听home键被点击,但有一个弊端就是点击home键app切换到后台后,在使用别的app点击home键 自己的app还是会收到这个广播,因为这是

    2024年02月11日
    浏览(37)
  • Android Glide

    1.引入glide 2.AndroidManifest.xml 中添加需要的权限 如果你计划从 URL 或一个网络连接中加载数据,你需要加 INTERNET 和 ACCESS_NETWORK_STATE 权限到你的 AndroidManifest.xml 中,要从本地文件夹或DCIM或图库中加载图片,你将需要添加 READ_EXTERNAL_STORAGE 权限。 3. 基本使用 Glide.with([fragment/Conte

    2024年04月12日
    浏览(36)
  • Android---Glide的基本使用

    目录 Glide 基本使用 Glide 进阶  Glide 是一个快速高效的 Android 图片加载库,可以自动加载网络、本地文件,app 资源中的图片,注重于平滑的滚动。 Glide 第一次加载一张图片后,就会自动帮我们把这张图片加入到内存中进行管理。 步骤1 :导入 Glide 依赖 步骤2: 最简单使用 wi

    2024年02月03日
    浏览(40)
  • Android——Glide的多样使用

    没有任何附加效果显示,请求结果返回之后,直接在图片容器中显示 当网络请求过多或者业务繁忙时,Glide返回可能会有一定延迟,此空窗期就会不显示任何东西,通过 placeholder 可添加一张占位符,在数据未返回之前,显示一张默认图片 在开发需求中,往往会需要将某些图

    2023年04月24日
    浏览(36)
  • [Android]图片加载库Glide

    目录 Glide的介绍  Glide的基本使用   指定图片的格式 Glide占位符  指定图片的大小  过渡动画 图片变换 Generated API Glide的介绍 Glide是一个快速高效的Android图片加载库,可以自动加载网络,本地文件,app资源中的文件,注重于平滑的滚动。 开源地址:https://github.com/bumptech/gl

    2024年02月08日
    浏览(46)
  • Android使用glide时报错“ ����: �޷�����Fragment Glide.with(getContext()) ^ �Ҳ���and”

    在 gradle.properties 中添加下面两行代码 即可

    2024年02月08日
    浏览(42)
  • Android Glide CustomTarget ,kotlin

    Android Glide CustomTarget ,kotlin       android Glide CustomViewTarget,java_zhangphil的博客-CSDN博客 【代码】android Glide CustomViewTarget,java。 https://blog.csdn.net/zhangphil/article/details/129493334 Android Glide预加载preload ,kotlin_zhangphil的博客-CSDN博客 【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然G

    2024年02月16日
    浏览(45)
  • Android之Glide图片框架分析

    使用简单,链式调用,API简洁。with、load、into三步走就可以加载图片 生命周期自动绑定,根据绑定的Activity或者Fragment生命周期管理图片请求 高效处理Bitmap。支持bitmap的复用和主动回收,减少系统回收压力。 占用内存小(使用RGB565的格式),RGB8888每个像素占的字节会比RGB5

    2024年02月13日
    浏览(41)
  • Android 加载gif图,Glide

    个人中心 DownLoad Android 可以使用 Glide、Picasso、Fresco 等第三方库来加载 gif 图。 以 Glide 为例,可以按照以下步骤加载 gif 图: 1. 在 build.gradle 文件中添加 Glide 的依赖: ``` dependencies {     implementation \\\'com.github.bumptech.glide:glide:4.12.0\\\'     annotationProcessor \\\'com.github.bumptech.glide:compil

    2024年02月14日
    浏览(43)
  • Android 面试之Glide做了哪些优化?

    Glide 可以说是最常用的图片加载框架了, Glide 链式调用使用方便,性能上也可以满足大多数场景的使用, Glide 源码与原理也是面试中的常客。 但是 Glide 的源码内容比较多,想要学习它的源码往往千头万绪,一时抓不住重点. 本文以 Glide 做了哪些优化为切入点,介绍与学习

    2024年02月11日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包