码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin


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

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

    build.gradle文件:

    1. plugins {
    2. id("org.jetbrains.kotlin.kapt")
    3. }
    4. implementation("com.github.bumptech.glide:glide:4.16.0")
    5. kapt("com.github.bumptech.glide:compiler:4.16.0")

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

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

    1. import android.content.Context
    2. import android.graphics.Bitmap
    3. import android.os.Bundle
    4. import android.provider.MediaStore
    5. import android.util.Log
    6. import android.view.LayoutInflater
    7. import android.view.View
    8. import android.view.ViewGroup
    9. import android.widget.TextView
    10. import androidx.appcompat.app.AppCompatActivity
    11. import androidx.appcompat.widget.AppCompatImageView
    12. import androidx.recyclerview.widget.GridLayoutManager
    13. import androidx.recyclerview.widget.RecyclerView
    14. import androidx.recyclerview.widget.RecyclerView.OnScrollListener
    15. import com.bumptech.glide.load.DataSource
    16. import com.bumptech.glide.load.engine.GlideException
    17. import com.bumptech.glide.request.RequestListener
    18. import com.bumptech.glide.request.target.Target
    19. import java.lang.ref.WeakReference
    20. const val PHOTO_SIZE = 150
    21. const val EMPTY = 0
    22. const val LOAD = 1
    23. class MainActivity : AppCompatActivity() {
    24. private val TAG = "Glide FLY"
    25. private var mItems = ArrayList()
    26. private var mLayoutManager: GridLayoutManager? = null
    27. private var mAdapter: MyAdapter? = null
    28. private var mVisibleItemPosition: IntArray? = null
    29. override fun onCreate(savedInstanceState: Bundle?) {
    30. super.onCreate(savedInstanceState)
    31. setContentView(R.layout.activity_main)
    32. init()
    33. mItems = readAllImage(applicationContext)
    34. mAdapter?.onChange(mItems)
    35. }
    36. override fun onResume() {
    37. super.onResume()
    38. Log.d(TAG, "onResume")
    39. }
    40. //当按了home键后,再次调出app,会进入onRestart
    41. override fun onRestart() {
    42. super.onRestart()
    43. Log.d(TAG, "onRestart")
    44. loadOnlyVisibleItem()
    45. }
    46. private fun loadOnlyVisibleItem() {
    47. Log.d(TAG, "可见区域 ${mVisibleItemPosition!![0]}->${mVisibleItemPosition!![1]}")
    48. for (i in mVisibleItemPosition!![0]..mVisibleItemPosition!![1]) {
    49. Log.d(TAG, "可见区域 ${mItems[i].pos} -- ${mItems[i].path}")
    50. }
    51. for (i in 0 until mItems.size) {
    52. if (i !in mVisibleItemPosition!![0]..mVisibleItemPosition!![1]) {
    53. if (mItems[i].status == LOAD) {
    54. mItems[i].targetRef?.get()?.let {
    55. GlideApp.with(this).clear(it)
    56. }
    57. mItems[i].status = EMPTY
    58. }
    59. }
    60. }
    61. }
    62. private fun getVisibleItemPosition(): IntArray {
    63. val first = mLayoutManager?.findFirstVisibleItemPosition()
    64. val last = mLayoutManager?.findLastVisibleItemPosition()
    65. return intArrayOf(first!!, last!!)
    66. }
    67. private fun init() {
    68. val spanCount = 8
    69. val rv = findViewById(R.id.recycler_view)
    70. mLayoutManager = GridLayoutManager(this, spanCount)
    71. rv.layoutManager = mLayoutManager
    72. rv.addOnScrollListener(object : OnScrollListener() {
    73. override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
    74. super.onScrolled(recyclerView, dx, dy)
    75. mVisibleItemPosition = getVisibleItemPosition()
    76. }
    77. })
    78. mAdapter = MyAdapter(this)
    79. rv.adapter = mAdapter
    80. }
    81. private fun readAllImage(context: Context): ArrayList {
    82. val photos = ArrayList()
    83. //读取手机图片
    84. val cursor = context.contentResolver.query(
    85. MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    86. null,
    87. null,
    88. null,
    89. null
    90. )
    91. while (cursor!!.moveToNext()) {
    92. //图片路径 uri
    93. val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))
    94. //图片名称
    95. //val name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME))
    96. //图片大小
    97. //val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE))
    98. photos.add(MyData(path))
    99. }
    100. cursor.close()
    101. return photos
    102. }
    103. }
    104. class MyAdapter(private val context: Context) : RecyclerView.Adapter() {
    105. private var items = ArrayList()
    106. fun onChange(items: ArrayList<MyData>) {
    107. this.items = items
    108. notifyDataSetChanged()
    109. }
    110. override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {
    111. val v = LayoutInflater.from(context).inflate(R.layout.item, parent, false)
    112. val params = v.layoutParams
    113. params.width = PHOTO_SIZE
    114. params.height = PHOTO_SIZE
    115. return MyVH(v)
    116. }
    117. override fun onBindViewHolder(holder: MyVH, position: Int) {
    118. load(holder, position)
    119. holder.text.text = "$position"
    120. }
    121. override fun getItemCount(): Int {
    122. return items.size
    123. }
    124. private fun load(holder: MyVH, position: Int) {
    125. items[position].pos = position
    126. items[position].status = LOAD
    127. val target: Target<*> = GlideApp.with(holder.itemView.context)
    128. .asBitmap()
    129. .load(items[position].path)
    130. .centerCrop()
    131. .addListener(object : RequestListener {
    132. override fun onLoadFailed(
    133. e: GlideException?,
    134. model: Any?,
    135. target: Target<Bitmap>,
    136. isFirstResource: Boolean
    137. ): Boolean {
    138. items[position].status = EMPTY
    139. return false
    140. }
    141. override fun onResourceReady(
    142. resource: Bitmap,
    143. model: Any,
    144. target: Target<Bitmap>?,
    145. dataSource: DataSource,
    146. isFirstResource: Boolean
    147. ): Boolean {
    148. holder.image.setImageBitmap(resource)
    149. items[position].status = EMPTY
    150. // 特别注意此处返回是true,而不能是false。
    151. // 因为如果返回false,当按home键把app切入后台后,再按app图标调出app切换到前台可见,反复切换,
    152. // 会造成Bitmap未回收的崩溃。
    153. return true
    154. }
    155. }).preload(
    156. PHOTO_SIZE,
    157. PHOTO_SIZE
    158. )
    159. items[position].targetRef = WeakReference(target)
    160. }
    161. }
    162. class MyVH(itemView: View) : RecyclerView.ViewHolder(itemView) {
    163. var image: AppCompatImageView
    164. var text: TextView
    165. init {
    166. image = itemView.findViewById(R.id.image)
    167. text = itemView.findViewById(R.id.text)
    168. }
    169. }
    170. class MyData(var path: String) {
    171. var targetRef: WeakReference>? = null
    172. var status = EMPTY
    173. var pos = 0
    174. }

    1. "1.0" encoding="utf-8"?>
    2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. xmlns:tools="http://schemas.android.com/tools"
    4. android:layout_width="match_parent"
    5. android:layout_height="match_parent"
    6. tools:context=".MainActivity">
    7. <androidx.recyclerview.widget.RecyclerView
    8. android:id="@+id/recycler_view"
    9. android:layout_width="match_parent"
    10. android:layout_height="match_parent" />
    11. RelativeLayout>

    1. "1.0" encoding="utf-8"?>
    2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. android:layout_width="wrap_content"
    4. android:layout_height="wrap_content"
    5. android:padding="1px">
    6. <androidx.appcompat.widget.AppCompatImageView
    7. android:id="@+id/image"
    8. android:layout_width="wrap_content"
    9. android:layout_height="wrap_content"
    10. android:scaleType="centerCrop"
    11. android:src="@drawable/ic_launcher_background" />
    12. <TextView
    13. android:id="@+id/text"
    14. android:layout_width="wrap_content"
    15. android:layout_height="wrap_content"
    16. android:layout_centerInParent="true"
    17. android:background="@android:color/holo_green_light"
    18. android:paddingLeft="1dp"
    19. android:paddingRight="1dp"
    20. android:text="-.-"
    21. android:textColor="@android:color/holo_red_dark"
    22. android:textSize="5dp" />
    23. RelativeLayout>

    1. import android.content.Context
    2. import android.util.Log
    3. import com.bumptech.glide.GlideBuilder
    4. import com.bumptech.glide.annotation.GlideModule
    5. import com.bumptech.glide.module.AppGlideModule
    6. @GlideModule
    7. class MyModule : AppGlideModule() {
    8. override fun applyOptions(context: Context, builder: GlideBuilder) {
    9. builder.setLogLevel(Log.DEBUG)
    10. }
    11. override fun isManifestParsingEnabled(): Boolean {
    12. return false
    13. }
    14. }

    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

  • 相关阅读:
    大一新生HTML期末作业,网页制作作业——明星介绍易烊千玺网站HTML+CSS
    汽车安全的未来:毫米波雷达在碰撞避免系统中的角色
    初探flask debug生成pin码
    【李航统计学习笔记】第八章:adaboost
    Selenium4+Python3系列(九) - 上传文件及滚动条操作
    泛海微FH511单片机IC方案小家电LED照明MCU丝印FH511
    vivo 海量基础数据计算架构应用实践
    猿创征文 | 开箱即用 yyg-cli:快速创建 vue3 组件库和vue3 全家桶项目
    Javaweb 之 Filter(过滤器)快速入门,执行流程,使用细节
    主机安全加固
  • 原文地址:https://blog.csdn.net/zhangphil/article/details/132592405
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号