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.WeakReferenceconst val PHOTO_SIZE = 150const val EMPTY = 0
const val LOAD = 1class MainActivity : AppCompatActivity() {private val TAG = "Glide FLY"private var mItems = ArrayList<MyData>()private var mLayoutManager: GridLayoutManager? = nullprivate var mAdapter: MyAdapter? = nullprivate var mVisibleItemPosition: IntArray? = nulloverride 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,会进入onRestartoverride 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 = 8val rv = findViewById<RecyclerView>(R.id.recycler_view)mLayoutManager = GridLayoutManager(this, spanCount)rv.layoutManager = mLayoutManagerrv.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()) {//图片路径 urival 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 = itemsnotifyDataSetChanged()}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {val v = LayoutInflater.from(context).inflate(R.layout.item, parent, false)val params = v.layoutParamsparams.width = PHOTO_SIZEparams.height = PHOTO_SIZEreturn 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 = positionitems[position].status = LOADval 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 = EMPTYreturn 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: AppCompatImageViewvar text: TextViewinit {image = itemView.findViewById(R.id.image)text = itemView.findViewById(R.id.text)}
}class MyData(var path: String) {var targetRef: WeakReference<Target<*>>? = nullvar status = EMPTYvar 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.RecyclerViewandroid: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.AppCompatImageViewandroid:id="@+id/image"android:layout_width="wrap_content"android:layout_height="wrap_content"android:scaleType="centerCrop"android:src="@drawable/ic_launcher_background" /><TextViewandroid: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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/117640.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

合宙Air724UG LuatOS-Air LVGL API控件--图表 (Chart)

图表 (Chart) 一幅图胜过一千个字&#xff0c;通过图表展示出的数据内容能让用户更快速有效的了解数据特征。 代码示例 – 创建图表 chart lvgl.chart_create(lvgl.scr_act(), nil) lvgl.obj_set_size(chart, 200, 150) lvgl.obj_align(chart, nil, lvgl.ALIGN_CENTER, 0, …

docker 笔记1

目录 1.为什么有docker ? 2.Docker 的核心概念 3.容器与虚拟机比较 3.1传统的虚拟化技术 3.2容器技术 3.3Docker容器的有什么作用&#xff1f; 3.4应用案例 4. docker 安装下载 4.1CentOS Docker 安装 4.2 Docker的基本组成 &#xff1f;&#xff08;面试&#xff09…

OpenShift 4 - 用 Prometheus 和 Grafana 监视用户应用定制的观测指标(视频)

《OpenShift / RHEL / DevSecOps 汇总目录》 说明&#xff1a;本文已经在 OpenShift 4.13 的环境中验证 文章目录 OpenShift 的监控功能构成部署被监控应用用 OpenShift 内置功能监控应用用 Grafana 监控应用安装 Grafana 运行环境配置 Grafana 数据源定制监控 Dashboard 演示视…

剑指 Offer 57 - II. 和为s的连续正数序列(简单)

题目&#xff1a; class Solution { public:vector<vector<int>> findContinuousSequence(int target) { //本题使用滑动窗口&#xff08;双指针&#xff09;int i1, j1; //定义左右边界&#xff0c;一般是左闭右开int sum0; //窗口内的和vector&…

弹性盒子的使用

一、定义 弹性盒子是一种用于按照布局元素的一维布局方法&#xff0c;它可以简便、完整、响应式地实现各种页面布局。 容器中存在两条轴&#xff0c;主轴和交叉轴(相当于我们坐标轴的x轴和y轴)。我们可以通过flex-direction来决定主轴的方向。 主轴&#xff08;main axis&am…

设计模式行为模式-命令模式

文章目录 前言定义结构工作原理优点适用场景消息队列模式Demo实现分写业务总结 前言 定义 命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;用于将请求封装为对象&#xff0c;从而使你可以使用不同的请求、队列或者日志请求来参数化其他对象…

MySQL高阶语句(三)

一、NULL值 在 SQL 语句使用过程中&#xff0c;经常会碰到 NULL 这几个字符。通常使用 NULL 来表示缺失 的值&#xff0c;也就是在表中该字段是没有值的。如果在创建表时&#xff0c;限制某些字段不为空&#xff0c;则可以使用 NOT NULL 关键字&#xff0c;不使用则默认可以为空…

zookeeper 集群

zookeeper 集群 1、zookeeper 集群说明 initLimit 是Zookeeper用它来限定集群中的Zookeeper服务器连接到Leader的时限 syncLimit 限制了follower服务器与leader服务器之间请求和应答之间的时限 服务器名称与地址&#xff1a;集群信息&#xff08;服务器编号&#xff0c;服务器…

kubesphere安装Maven+JDK17 流水线打包

kubesphere 3.4.0版本&#xff0c;默认支持的jav版本是8和11&#xff0c;不支持17 。需要我们自己定义JenKins Agent 。方法如下&#xff1a; 一、构建镜像 1、我们需要从Jenkins Agent的github仓库拉取master最新源码&#xff0c;最新源码里已经支持jdk17了。 git clone ht…

代码随想录算法训练营第39天 | ● 62.不同路径 ● 63. 不同路径II

文章目录 前言一、62.不同路径二、63.不同路径II总结 前言 动态规划 一、62.不同路径 深搜动态规划数论 深搜&#xff1a; 注意题目中说机器人每次只能向下或者向右移动一步&#xff0c;那么其实机器人走过的路径可以抽象为一棵二叉树&#xff0c;而叶子节点就是终点&#…

JS算法与树(二)

前言 二叉搜索树&#xff08;BST&#xff09;存在一个问题&#xff1a;当你添加的节点数够多的时候&#xff0c;树的一边可能会非常的深。而其他的分支却只有几层。 AVL树 为了解决上面的问题&#xff0c;我们提出一种自平衡二叉搜索树。意思是任何一个节点左右两侧子树的高度之…

多级缓存 架构设计

说在前面 在40岁老架构师 尼恩的读者社区(50)中&#xff0c;很多小伙伴拿到一线互联网企业如阿里、网易、有赞、希音、百度、网易、滴滴的面试资格&#xff0c;多次遇到一个很重要的面试题&#xff1a; 20w的QPS的场景下&#xff0c;服务端架构应如何设计&#xff1f;10w的QPS…

python爬虫-Selenium

一、Selenium简介 Selenium是一个用于Web应用程序测试的工具&#xff0c;Selenium 测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样。模拟浏览器功能&#xff0c;自动执行网页中的js代码&#xff0c;实现动态加载。 二、环境配置 1、查看本机电脑谷歌浏览器的版…

Qt之进程通信-IPC(QLocalServer,QLocalSocket 含源码+注释)

文章目录 一、IPC通信示例图1.1 设置关键字并连接的示例图1.2 进程间简单的数据通信示例图1.3 断开连接的示例图1.3.1 由Server主动断开连接1.3.2 由Socket主动断开连接 1.4 Server停止监听后的效果二、个人理解与一些心得三、一些疑问&#xff08;求教 家人们&#x1f602;&am…

【ES6】JavaScript的Proxy:理解并实现高级代理功能

在JavaScript中&#xff0c;Proxy是一种能够拦截对对象的读取、设置等操作的机制。它们提供了一种方式&#xff0c;可以在执行基本操作之前或之后&#xff0c;对这些操作进行自定义处理。这种功能在许多高级编程场景中非常有用&#xff0c;比如实现数据验证、日志记录、权限控制…

【网络教程】群晖如何正确的安装openwrt旁路由

文章目录 准备安装导入镜像创建虚拟机访问旁路由旁路由网络设置准备 我这里的环境是群晖DSM7.2版本首先大家需要预先安装套件Virtual Machine Manager,这里就省略了 根据个人需求去下载openwrt的固件,下载的时候选择x86的img镜像文件,这里也可以直接使用我使用的这个固件(资…

RISC-V 中国峰会 | OpenMPL引人注目,RISC-V Summit China 2023圆满落幕

RISC-V中国峰会圆满落幕 2023年8月25日&#xff0c;为期三天的RISC-V中国峰会&#xff08;RISC-V Summit China 2023&#xff09;圆满落幕。本届峰会以“RISC-V生态共建”为主题&#xff0c;结合当下全球新形势&#xff0c;把握全球新时机&#xff0c;呈现RISC-V全球新观点、新…

8.27周报

文章目录 前言论文阅读摘要介绍模型算法 总结 前言 本周学习了GAN论文《Generative Adversarial Nets》&#xff0c;了解GAN主要由两部分组成&#xff1a;生成器和判别器&#xff0c;知道生成器G和判别器D的作用及原理&#xff0c;相比于其他的生成模型&#xff0c;了解GAN的优…

Postman的高级用法—Runner的使用​

1.首先在postman新建要批量运行的接口文件夹&#xff0c;新建一个接口&#xff0c;并设置好全局变量。 2.然后在Test里面设置好要断言的方法 如&#xff1a; tests["Status code is 200"] responseCode.code 200; tests["Response time is less than 10000…

自建音乐播放器之一

这里写自定义目录标题 1.1 官方网站 2. Navidrome 简介2.1 简介2.2 特性 3. 准备工作4. 视频教程5. 界面演示5.1 初始化页5.2 专辑页 前言 之前给大家介绍过 Koel 音频流服务&#xff0c;就是为了解决大家的这个问题&#xff1a;下载下来的音乐&#xff0c;只能在本机欣赏&…