Android优化RecyclerView图片展示:Glide成堆加载批量Bitmap在RecyclerView成片绘制Canvas,Kotlin(b)

本文主要是介绍Android优化RecyclerView图片展示:Glide成堆加载批量Bitmap在RecyclerView成片绘制Canvas,Kotlin(b),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android优化RecyclerView图片展示:Glide成堆加载批量Bitmap在RecyclerView成片绘制Canvas,Kotlin(b)

对 Android GridLayoutManager Glide批量加载Bitmap绘制Canvas画在RecyclerView,Kotlin(a)-CSDN博客 改进,用Glide批量把Bitmap加载出来,然后在RecyclerView成片成堆的绘制Canvas,此种实现是RecyclerView加载多宫格图片展示,卡顿丢帧最低的一种实现,上下滑动流畅。

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

plugins {id 'org.jetbrains.kotlin.kapt'
}implementation 'com.github.bumptech.glide:glide:4.16.0'kapt 'com.github.bumptech.glide:compiler:4.16.0'

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.cache.InternalCacheDiskCacheFactory
import com.bumptech.glide.load.engine.cache.MemorySizeCalculator
import com.bumptech.glide.load.engine.executor.GlideExecutor
import com.bumptech.glide.module.AppGlideModule@GlideModule
class MyGlideModule : AppGlideModule() {override fun applyOptions(context: Context, builder: GlideBuilder) {super.applyOptions(context, builder)builder.setLogLevel(Log.DEBUG)val memoryCacheScreens = 200Fval maxSizeMultiplier = 0.8Fval calculator = MemorySizeCalculator.Builder(context).setMemoryCacheScreens(memoryCacheScreens).setBitmapPoolScreens(memoryCacheScreens).setMaxSizeMultiplier(maxSizeMultiplier).setLowMemoryMaxSizeMultiplier(maxSizeMultiplier * 0.8F).setArrayPoolSize((1024 * 1024 * memoryCacheScreens).toInt()).build()builder.setMemorySizeCalculator(calculator)val diskCacheSize = 1024 * 1024 * 2000Lbuilder.setDiskCache(InternalCacheDiskCacheFactory(context, diskCacheSize))val mSourceExecutor = GlideExecutor.newSourceBuilder().setUncaughtThrowableStrategy(GlideExecutor.UncaughtThrowableStrategy.LOG).setThreadCount(4)//.setThreadTimeoutMillis(1000) //线程读写超时时间。.setName("fly-SourceExecutor").build()val mDiskCacheBuilder = GlideExecutor.newDiskCacheBuilder().setThreadCount(1)//.setThreadTimeoutMillis(1000) //线程读写超时时间。.setName("fly-DiskCacheBuilder").build()val mAnimationExecutor = GlideExecutor.newDiskCacheBuilder().setThreadCount(1)//.setThreadTimeoutMillis(1000) //线程读写超时时间。.setName("fly-AnimationExecutor").build()builder.setSourceExecutor(mSourceExecutor)builder.setDiskCacheExecutor(mDiskCacheBuilder)builder.setAnimationExecutor(mAnimationExecutor)}override fun isManifestParsingEnabled(): Boolean {return false}
}

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.provider.MediaStore
import android.util.AttributeSet
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.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.google.android.material.imageview.ShapeableImageView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.math.ceil
import kotlin.math.roundToIntconst val COLUMN_COUNT = 16 // 一行多少个图片。
const val CHUNKED_SIZE = 100 // 一批/一大片总共有多少张图片。class MainActivity : AppCompatActivity() {companion object {const val TAG = "fly"const val VIEW_TYPE = 0 //图片区域。const val GROUP_TYPE = 1 //分组标签。}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val rv = findViewById<RecyclerView>(R.id.rv)val layoutManager = LinearLayoutManager(this)layoutManager.orientation = LinearLayoutManager.VERTICALrv.layoutManager = layoutManagerval adapter = MyAdapter(this)rv.adapter = adapterrv.setHasFixedSize(true)lifecycleScope.launch(Dispatchers.IO) {val items = readAllImage(this@MainActivity)items.reverse()val lists: ArrayList<AdapterData> = sliceDataList(items)withContext(Dispatchers.Main) {adapter.dataChanged(lists)}}}class MyAdapter : RecyclerView.Adapter<MyVH> {private var mItems = arrayListOf<AdapterData>()private var mContext: Context? = nullconstructor(ctx: Context) {this.mContext = ctx}fun dataChanged(items: ArrayList<AdapterData>) {this.mItems = itemsnotifyDataSetChanged()}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {return when (viewType) {GROUP_TYPE -> {val view = LayoutInflater.from(mContext!!).inflate(android.R.layout.simple_list_item_1, parent, false)view.setBackgroundColor(ContextCompat.getColor(mContext!!, android.R.color.darker_gray))MyVH(view)}else -> {val view = BatchBitmapView(mContext!!)MyVH(view)}}}override fun getItemCount(): Int {return mItems.size}override fun getItemViewType(position: Int): Int {return mItems[position].type}override fun onBindViewHolder(holder: MyVH, position: Int) {Log.d(TAG, "onBindViewHolder $position")when (getItemViewType(position)) {GROUP_TYPE -> {holder.itemView.findViewById<TextView>(android.R.id.text1).text = "$position GROUP"}else -> {(holder.itemView as BatchBitmapView).setRowBitmapData(mItems[position].mediaData)}}}}class MyVH : RecyclerView.ViewHolder {constructor(itemView: View) : super(itemView) {}}class AdapterData(var type: Int = GROUP_TYPE, data: List<MediaData>? = null) {var mediaData: List<MediaData>? = data}class MediaData(var path: String, var index: Int)private fun sliceDataList(data: ArrayList<MediaData>): ArrayList<AdapterData> {val lists = ArrayList<AdapterData>()val chunks = data.chunked(CHUNKED_SIZE)chunks.forEach {lists.add(AdapterData(GROUP_TYPE))lists.add(AdapterData(VIEW_TYPE, it))}return lists}private fun readAllImage(context: Context): ArrayList<MediaData> {val photos = ArrayList<MediaData>()//读取所有图片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(MediaData(path, index++))}cursor.close()return photos}
}class BatchBitmapView : ShapeableImageView {private val mData = mutableListOf<DataBean>()private val mScreenWidth = resources.displayMetrics.widthPixelsprivate val mTargets = mutableListOf<CustomTarget<Bitmap>>()private var mContext: Context? = nullprivate var mImageSize = 0 //每个小格子图片的尺寸,动态计算而变化。companion object {const val TAG = "BatchBitmapView"}constructor(ctx: Context,attributeSet: AttributeSet? = null,defStyleAttr: Int = 0) : super(ctx, attributeSet, defStyleAttr) {mContext = ctxmImageSize = (mScreenWidth.toFloat() / COLUMN_COUNT.toFloat()).roundToInt()}fun setRowBitmapData(rows: List<MainActivity.MediaData>?) {mData.clear()Log.d(TAG, "mTargets.size=${mTargets.size}")mTargets.forEach {GlideApp.with(mContext!!).clear(it) //如果不清除,会发生有些图错放位置。}mTargets.clear() //mTargets上下滑动列表会越来越大,清空,一直保持ROW_SIZE.rows?.forEachIndexed { index, data ->val target = object : CustomTarget<Bitmap>() {override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {val bean = DataBean(resource)mData.add(bean)postInvalidate()}override fun onLoadCleared(placeholder: Drawable?) {}}GlideApp.with(mContext!!).asBitmap().centerCrop().override(mImageSize).load(data.path).into(target)mTargets.add(target)}}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {super.onMeasure(widthMeasureSpec, heightMeasureSpec)val rows = ceil(CHUNKED_SIZE.toFloat() / COLUMN_COUNT.toFloat()).toInt()setMeasuredDimension(mScreenWidth, mImageSize * rows)}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)mData.forEachIndexed { index, dataBean ->//canvas.save()val left = mImageSize * (index % COLUMN_COUNT)val top = (index / COLUMN_COUNT) * mImageSizecanvas.drawBitmap(dataBean.bitmap, left.toFloat(), top.toFloat(), null)//canvas.restore()}}data class DataBean(val bitmap: Bitmap)
}

Android GridLayoutManager Glide批量加载Bitmap绘制Canvas画在RecyclerView,Kotlin(a)-CSDN博客【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用户的头像是从服务器端读出的一个普通矩形图片,但是现在的设计一般要求在APP端的用户头像显示成圆形头像,那么此时虽然Glide可以加载,但加载出来的是一个矩形,如果要Glide_android 毛玻璃圆角。现在结合他人的代码加以修改,给出一个以原始图形中心为原点,修剪图片为头像的工具类,此类可以直接在布局文件中加载使用,比。文章浏览阅读670次。https://blog.csdn.net/zhangphil/article/details/137823405

Android RecyclerView性能优化及Glide流畅加载图片丢帧率低的一种8宫格实现,Kotlin-CSDN博客文章浏览阅读695次,点赞26次,收藏11次。【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用户的头像是从服务器端读出的一个普通矩形图片,但是现在的设计一般要求在APP端的用户头像显示成圆形头像,那么此时虽然Glide可以加载,但加载出来的是一个矩形,如果要Glide_android 毛玻璃圆角。现在结合他人的代码加以修改,给出一个以原始图形中心为原点,修剪图片为头像的工具类,此类可以直接在布局文件中加载使用,比。文章浏览阅读670次。https://blog.csdn.net/zhangphil/article/details/137653692Android GridLayoutManager SpanSizeLookup dynamic set grid cell column count,Kotlin-CSDN博客文章浏览阅读584次,点赞6次,收藏7次。Android RecyclerView的StaggeredGridLayoutManager实现交错排列的子元素分组先看实现的结果如图:设计背景:现在的产品对设计的需求越来越多样化,如附录文章2是典型的联系人分组RecyclerView,子元素排列到一个相同的组,但是有些时候,UI要求把这些元素不是垂直方向的,而是像本文开头的图中所示样式排列,这就需要用StaggeredGridLayoutMa_staggeredgridlayoutmanager。https://blog.csdn.net/zhangphil/article/details/137694645Android Glide load grid RecyclerView scroll smooth, high performance and ,Kotlin-CSDN博客文章浏览阅读709次,点赞18次,收藏13次。【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,往往用户的头像是从服务器端读出的一个普通矩形图片,但是现在的设计一般要求在APP端的用户头像显示成圆形头像,那么此时虽然Glide可以加载,但加载出来的是一个矩形,如果要Glide_android 毛玻璃圆角。现在结合他人的代码加以修改,给出一个以原始图形中心为原点,修剪图片为头像的工具类,此类可以直接在布局文件中加载使用,比。文章浏览阅读670次。https://blog.csdn.net/zhangphil/article/details/137520793

这篇关于Android优化RecyclerView图片展示:Glide成堆加载批量Bitmap在RecyclerView成片绘制Canvas,Kotlin(b)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/917363

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份

【WebGPU Unleashed】1.1 绘制三角形

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123 在 3D 渲染领域,三角形是最基本的绘制元素。在这里,我们将学习如何绘制单个三角形。接下来我们将制作一个简单的着色器来定义三角形内的像素

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存