Android Glide预处理preload原始图片到成品resource 预加载RecyclerViewPreloader,Kotlin

news/2025/1/13 10:44:59/

Android Glide预处理preload原始图片到成品resource & 预加载RecyclerViewPreloader,Kotlin

 

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

 

 

    implementation 'com.github.bumptech.glide:glide:4.15.1'kapt 'com.github.bumptech.glide:compiler:4.15.1'implementation ("com.github.bumptech.glide:recyclerview-integration:4.15.1") {// Excludes the support library because it's already included by Glide.transitive = false}

 

 

import android.content.Context
import android.util.Log
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool
import com.bumptech.glide.load.engine.cache.LruResourceCache
import com.bumptech.glide.module.AppGlideModule@GlideModule
class MyModule : AppGlideModule() {companion object {val mLruResourceCache = LruResourceCache(1024 * 1024 * 9999)val mLruBitmapPool = LruBitmapPool(1024 * 1024 * 9999)fun debug(msg: String) {Log.d(TAG,"$msg")}}override fun applyOptions(context: Context, builder: GlideBuilder) {builder.setMemoryCache(mLruResourceCache)builder.setBitmapPool(mLruBitmapPool)builder.setLogLevel(Log.DEBUG)Log.d(TAG, "自定义配置")super.applyOptions(context, builder)}override fun isManifestParsingEnabled(): Boolean {return false}
}

 

 

<?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"tools:context=".MainActivity" /></RelativeLayout>
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 com.bumptech.glide.ListPreloader
import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.util.FixedPreloadSizeProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContextconst val PHOTO_SIZE = 80
const val TAG = "MyGlide"
const val preloadSize = 100class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)rvPreload()}private fun rvPreload() {val spanCount = 13var recyclerView: RecyclerView = findViewById(R.id.recycler_view)recyclerView?.layoutManager = GridLayoutManager(this, spanCount).apply {orientation = GridLayoutManager.VERTICAL}val adapter = MyAdapter(this)recyclerView?.adapter = adapterval heightCount = resources.displayMetrics.heightPixels / PHOTO_SIZEval max = 10 * heightCount * spanCount//如果没有句已加载且展示的格子再滑回去会出现残缺白块行。recyclerView.recycledViewPool.setMaxRecycledViews(0, max)CoroutineScope(Dispatchers.IO).launch {val items = readAllImage(applicationContext)//以len为长度值,将原始的列表切分为 [0-(len-1)],[len-列表结尾]两条。//第一条较短,快速完成原始图片预处理,紧急为用户快速展示图片(此时Glide将从resource直接装入内存)//第二条很长,适合在app冷启动后,后台静默加载。val len = 600val segment1 = items.subList(0, len)val segment2 = items.subList(len, items.size - 1)Log.d(TAG, "预处理 $len ...")segment1.forEachIndexed { index, myData ->glidePreload(myData)}Log.d(TAG, "预处理 $len")// 这段时间是拍脑瓜拍出来的。// Glide需要一定时间才能完成len个资源的预处理,把原始数据转换为resource成品。// 如果不等待不延迟,直接通知adapter更新数据,绝大多数情况下,Glide此时还没来得及完成预处理,没有预处理快速显示的效果。delay(10_000L)withContext(Dispatchers.Main) {Log.d(TAG, "预处理 $len done")adapter.onChange(items)}Log.d(TAG, "预处理 第二批 ...")segment2.forEachIndexed { index, myData ->glidePreload(myData)}}val preloadSizeProvider = FixedPreloadSizeProvider<MyData>(PHOTO_SIZE,PHOTO_SIZE)val preloadModelProvider = MyPreloadModelProvider(this, adapter)val preloader: RecyclerViewPreloader<MyData> = RecyclerViewPreloader(GlideApp.with(this),preloadModelProvider,preloadSizeProvider,preloadSize)recyclerView?.addOnScrollListener(preloader)}private fun glidePreload(myData: MyData) {//本身是线程化的,很快返回,不阻塞主线程。Glide将在后台线程中decode原始图片,加工成resource成品。GlideApp.with(this).asBitmap().load(myData.path).centerCrop().override(PHOTO_SIZE).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).preload(PHOTO_SIZE, PHOTO_SIZE)}class MyPreloadModelProvider(private val ctx: Context,private val adapter: MyAdapter,) : ListPreloader.PreloadModelProvider<MyData> {override fun getPreloadItems(position: Int): MutableList<MyData> {return mutableListOf(adapter.getItems()[position])}override fun getPreloadRequestBuilder(item: MyData): GlideRequest<Bitmap>? {return GlideApp.with(ctx).asBitmap().load(item.path).centerCrop().override(PHOTO_SIZE)}}class MyAdapter(private val ctx: Context) :RecyclerView.Adapter<MyViewHolder>() {private var items: MutableList<MyData>? = nullfun onChange(items: MutableList<MyData>) {this.items = itemsnotifyDataSetChanged()}fun getItems(): MutableList<MyData> {return items!!}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val view = LayoutInflater.from(ctx).inflate(R.layout.item, parent, false)val params = view.layoutParamsparams.width = PHOTO_SIZEparams.height = PHOTO_SIZEreturn MyViewHolder(view)}override fun onBindViewHolder(holder: MyViewHolder, position: Int) {GlideApp.with(ctx).asBitmap().centerCrop().override(PHOTO_SIZE, PHOTO_SIZE).load(items?.get(position)?.path).into(holder.image)holder.text.text = "$position"}override fun getItemCount(): Int {return items?.size ?: 0}//        override fun getItemId(position: Int): Long {
//            return RecyclerView.NO_ID
//        }override fun getItemViewType(position: Int): Int {return 0}}class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {val image: AppCompatImageView = itemView.findViewById(R.id.image)val text: TextView = itemView.findViewById(R.id.text)}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)var index = 0while (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, index++))}cursor.close()return photos}class MyData(var path: String, val index: Int)
}

 

<?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:text="-.-"android:textColor="@android:color/holo_red_dark"android:textSize="8dp" />
</RelativeLayout>

 

 

 

 

 

Android GlideApp FixedPreloadSizeProvider RecyclerViewPreloader,mix Java&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/131905329Android GlideApp GlideRequest FixedPreloadSizeProvider 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/131813200

 


http://www.ppmy.cn/news/990160.html

相关文章

uniAPP 浙政钉 入门手册

uniAPP 如何运行钉钉小程序&#xff1a; 运行钉钉小程序 调试工具导入项目 及 相关平台使用&#xff1a; 专有钉钉 浙政钉 前端 对接流程 常见调试工具&#xff0c;遇到的问题&#xff1a; 采坑记录 下载小程序 IDE 环境配置文件 专有钉钉–环境配置文件

Ansible最佳实践之Playbook管理滚动更新

写在前面 理解不足小伙伴帮忙指正 傍晚时分&#xff0c;你坐在屋檐下&#xff0c;看着天慢慢地黑下去&#xff0c;心里寂寞而凄凉&#xff0c;感到自己的生命被剥夺了。当时我是个年轻人&#xff0c;但我害怕这样生活下去&#xff0c;衰老下去。在我看来&#xff0c;这是比死亡…

CentOS系统启动过程

CentOS系统启动流程图 &#xff08;1&#xff09; 加载 BIOS 计算机电源加电质检&#xff0c;首先加载基本输入输出系统&#xff08;Basic Input Output System&#xff0c;BIOS&#xff09;&#xff0c;BIOS 中包含硬件 CPU、内存、硬盘等相关信息&#xff0c;包含设备启动顺序…

联发科CEO:未获准向华为供货,换机潮已过去,手机需求不会更差

据钜亨网报道&#xff0c;联发科近期召开了业绩说明会。蔡力行&#xff0c;该公司副董事长兼首席执行官&#xff0c;表明当前手机市场需求保持稳定&#xff0c;并且随着过去两年用户更换潮的过去&#xff0c;对手机市场明年有一定期望。 根据蔡力行的指示&#xff0c;联发科正在…

算法刷题Day 50 买卖股票的最佳时机III+买卖股票的最佳时机IV

Day 50 动态规划 123. 买卖股票的最佳时机III 前两道题的结合&#xff0c;需要更多位置来记录状态 class Solution { public:int maxProfit(vector<int>& prices) {vector<vector<int>> dp(prices.size(), vector<int>(5, 0));dp[0][1] -price…

UE5 C++ SplineMesh蓝图函数库实现(小白笔记)

UE5 C SplineMesh的蓝图函数库实现方法 UAAABlueprintFunctionLibrary UAAABlueprintFunctionLibrary.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "Components/Spline…

第一次后端复习整理(JVM、Redis、反射)

1. JVM 文章仅为自身笔记 详情查看一篇文章掌握整个JVM&#xff0c;JVM超详细解析&#xff01;&#xff01;&#xff01; 1.1 什么是JVM jvm是Java虚拟机 1.2 Java文件的编译过程 程序员编写代码形成.java文件经过javac编译成.class文件再通过JVM的类加载器进入运行时数据…

C++ vector元素类型为什么不能是引用

文章目录 一、引用特征二、不能为引用分配内存三、push_back(T&)不能赋值四、vector引用类型不能进行有参构造五、基于操作符[]和at,将会获取引用的引用&#xff0c;产生矛盾 vector<T&> 一、引用特征 引用必须要进行初始化&#xff0c;不能初始化为空对象&#…