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.mzph.cn/news/59734.shtml

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

相关文章

算法-图BFS/DFS-单词接龙

算法-图BFS/DFS-单词接龙 1 题目概述 1.1 题目出处 https://leetcode-cn.com/problems/number-of-islands 1.2 题目描述 给定两个单词&#xff08;beginWord 和 endWord&#xff09;和一个字典&#xff0c;找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如…

C++八股记录

C内存管理 C中&#xff0c;内存分成5个区。 栈&#xff1a;函数内局部变量&#xff1b;自动管理&#xff0c;效率高&#xff0c;但空间较小&#xff1b; 堆&#xff1a;new分配的内存块&#xff1b;手动管理&#xff0c;效率低&#xff0c;但空间大&#xff1b; 自由存储区&…

弯道超车必做好题集锦三(C语言选择题)

前言&#xff1a; 编程想要学的好&#xff0c;刷题少不了&#xff0c;我们不仅要多刷题&#xff0c;还要刷好题&#xff01;为此我开启了一个弯道超车必做好题锦集的系列&#xff0c;每篇大约10题左右。此为第三篇选择题篇&#xff0c;该系列会不定期更新&#xff0c;后续还会…

全面解析MES系统中的报工操作

一、报工操作的定义&#xff1a; 报工操作是指在生产过程中&#xff0c;操作员通过MES系统记录和提交生产工序的相关信息&#xff0c;如工时、产量、质量等。报工操作将生产过程中的实际情况反馈给MES系统&#xff0c;实现生产数据的实时采集和记录。 二、报工操作的流程&…

MacOS goland go1.21 debug问题

安装dlv brew install dlv 安装之后在终端会显示所在目录 类似/usr/local/Cellar/delve/1.21.0/bin 配置goland 在文件系统中找到goland 右击选择show package contents -> Contents -> plugins -> go 尝试替换 其中对应系统 的 dlv 结果还是不行 然后打开应用gol…

常见前端面试之VUE面试题汇总七

20. 对 vue 设计原则的理解 1.渐进式 JavaScript 框架&#xff1a;与其它大型框架不同的是&#xff0c;Vue 被设计 为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上 手&#xff0c;还便于与第三方库或既有项目整合。另一方面&#xff0c;当与现代化的…

universal robot 机械臂 官方基本教程

https://academy.universal-robots.cn/modules/e-Series-core-track/Chinese/module3/story_html5.html?courseId2166&languageChinese 教程1 控制箱内部 包含&#xff1a; 主机板&#xff0c;SD卡&#xff0c;和安全控制板 安全控制板负责所有控制信息&#xff0c;包括…

LeetCode(力扣)617. 合并二叉树Python

LeetCode617. 合并二叉树 题目链接代码 题目链接 https://leetcode.cn/problems/merge-two-binary-trees/ 代码 递归 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # …

【springboot】springboot定时任务:

文章目录 一、文档&#xff1a;二、案例&#xff1a; 一、文档&#xff1a; 【cron表达式在线生成器】https://cron.qqe2.com/ 二、案例&#xff1a; EnableScheduling //开启任务调度package com.sky.task;import com.sky.entity.Orders; import com.sky.mapper.OrderMapper; …

LeetCode-160. 相交链表

这是一道真的非常巧妙的题&#xff0c;题解思路如下&#xff1a; 如果让他们尾端队齐&#xff0c;那么从后面遍历就会很快找到第一个相交的点。但是逆序很麻烦。 于是有一个巧妙的思路诞生了&#xff0c;如果让短的先走完自己的再走长的&#xff0c;长的走完走短的&#xff0c;…

MyBatisx代码生成

MyBatisx代码生成 1.创建数据库表 CREATE TABLE sys_good (good_id int(11) NOT NULL,good_name varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,good_desc varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,PRIMARY KEY (good_id) ) ENGINEInnoDB DEFAULT CHA…

Multisim软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Multisim软件是一款电路仿真和设计软件&#xff0c;由美国国家仪器公司&#xff08;National Instruments&#xff09;开发。它提供了一个交互式的图形界面&#xff0c;使用户能够轻松地构建和仿真电路。以下是Multisim软件的详…

nowcoder NC236题 最大差值

目录 题目描述&#xff1a; 示例1 示例2 题干解析&#xff1a; 暴力求解&#xff1a; 代码展示&#xff1a; 优化&#xff1a; 代码展示&#xff1a; 题目跳转https://www.nowcoder.com/practice/a01abbdc52ba4d5f8777fb5dae91b204?tpId128&tqId33768&ru/exa…

Typora mac版本安装

提示&#xff1a;文章介绍&#xff0c;Typora在Mac系统中免费安装使用 文章目录 一、官网下载二、安装 一、官网下载 官网地址&#xff1a;https://www.typoraio.cn/ 二、安装 安装好后按 command 空格键&#xff0c;找到 Typora的安装路径 /Applications/Typora.app/Con…

Kubernetes(七)修改 pod 网络(flannel 插件)

一、 提示 需要重启服务器 操作之前备份 k8s 中所有资源的 yaml 文件 如下是备份脚本&#xff0c;仅供参考 # 创建备份目录 test -d $3 || mkdir $3 # $1 命名空间 # $2 资源名称&#xff1a; sts deploy configMap svc 等 # $3 资源备份存放的目录名称for app in kubec…

oauth2.0第2季 分布式认证与授权实现单点登录

一 oauth介绍 1.0 疑问汇总 1.使用jwttoken进行令牌传输&#xff0c;资源服务器在本地怎么验证token&#xff1f; 1.1 oauth的基础内容 1.1.1 oauth是什么 1.1.2 oauth的角色 1.1.3 oauth的认证流程 1.1.4 oauth的4种模式 1.2 为何要用oauth2.0 1.介绍单体架构 使用ses…

k8s节点pod驱逐、污点标记

一、设置污点&#xff0c;禁止pod被调度到节点上 kubectl cordon k8s-node-145 设置完成后&#xff0c;可以看到该节点附带了 SchedulingDisabled 的标记 二、驱逐节点上运行的pod到其他节点 kubectl drain --ignore-daemonsets --delete-emptydir-data k8s-node-145 显示被驱逐…

Android需要掌握的shell脚本基础

linux中sh是链接到bash上的&#xff0c;所以sh与bash在功能上是没有区别的&#xff0c;相当于bash解析器是sh的增强版本&#xff0c;所以安卓开发者可以在 git bash中 测试脚本 1&#xff0c;shell脚本运行与输出指令 $ cat test.sh echo 测试 【输出】$ /bin/bash test.…

LeetCode第26~30题解

CONTENTS LeetCode 26. 删除有序数组中的重复项&#xff08;简单&#xff09;LeetCode 27. 移除元素&#xff08;简单&#xff09;LeetCode 28. 找出字符串中第一个匹配项的下标&#xff08;简单&#xff09;LeetCode 29. 两数相除&#xff08;中等&#xff09;LeetCode 30. 串…

qt设计界面

widget.h #ifndef WIDGET_H #define WIDGET_H //防止文件重复包含#include <QWidget> //QWidget类所在的头文件&#xff0c;父类头文件 #include<QIcon> #include<QPushButton> …