Android Glide预加载RecyclerViewPreloader,ViewPreloadSizeProvider,kotlin

news2024/9/22 21:35:48

Android Glide预加载RecyclerViewPreloader,ViewPreloadSizeProvider,kotlin

 

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

 

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

 

 

import android.content.Context
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.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.ListPreloader
import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader
import com.bumptech.glide.util.ViewPreloadSizeProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File


class MainActivity : AppCompatActivity() {
    companion object {
        const val TAG = "fly"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var recyclerView: RecyclerView = findViewById(R.id.recycler_view)
        recyclerView?.layoutManager = GridLayoutManager(this, 3).apply {
            orientation = GridLayoutManager.VERTICAL
        }

        val adapter = MyAdapter()
        recyclerView?.adapter = adapter

        CoroutineScope(Dispatchers.IO).launch {
            val items = readAllImage(applicationContext)
            withContext(Dispatchers.Main) {
                adapter.onChange(items)
            }
        }

        var preloadSizeProvider = ViewPreloadSizeProvider<MyData>()
        val preloadModelProvider = MyPreloadModelProvider(adapter, this)
        val preloader = RecyclerViewPreloader(
            this,
            preloadModelProvider,
            preloadSizeProvider,
            100 //maxPreload预加载数量
        )

        recyclerView?.addOnScrollListener(preloader)
    }

    class MyPreloadModelProvider(
        private val adapter: MyAdapter,
        private val context: Context
    ) : ListPreloader.PreloadModelProvider<MyData> {
        // 从当前屏幕结束的位置开始,再加载maxPreload条item,
        // 不可见的item即为屏幕外的position位置
        // 如果对于一个给定的位置不需要加载任何东西,getPreloadItems 可以返回一个空表。
        override fun getPreloadItems(position: Int): MutableList<MyData> {
            val data: MyData = adapter.getItems()[position]
            Log.d(TAG, "getPreloadItems pos:$position index:${data.index}")
            return mutableListOf(data)
        }

        override fun getPreloadRequestBuilder(item: MyData): RequestBuilder<*>? {
            Log.d(TAG, "getPreloadRequestBuilder ${item.index}")
            return Glide.with(context).load(File(item.path))
        }
    }

    class MyAdapter : RecyclerView.Adapter<MyViewHolder>() {
        private var items: ArrayList<MyData>? = null

        fun onChange(items: ArrayList<MyData>?) {
            this.items = items
            notifyDataSetChanged()
        }

        fun getItems(): ArrayList<MyData> {
            return items!!
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.item, parent, false)
            return MyViewHolder(view)
        }

        override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
            Glide.with(holder.itemView.context).load(File(items?.get(position)?.path))
                .into(holder.image)
        }

        override fun getItemCount(): Int {
            return items?.size ?: 0
        }
    }

    class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val image: ImageView = itemView.findViewById(R.id.image)
    }

    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 = 0
        while (cursor!!.moveToNext()) {
            //图片路径
            val 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"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/image"
    android:layout_width="100dp"
    android:layout_height="100dp" />

 

 

 

 

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/131592226Android load all photos into RecyclerView,pinch to zoom by ScaleGestureDetector,kotlin(4)_zhangphil的博客-CSDN博客Android RecyclerView的StaggeredGridLayoutManager实现交错排列的子元素分组先看实现的结果如图:设计背景:现在的产品对设计的需求越来越多样化,如附录文章2是典型的联系人分组RecyclerView,子元素排列到一个相同的组,但是有些时候,UI要求把这些元素不是垂直方向的,而是像本文开头的图中所示样式排列,这就需要用StaggeredGridLayoutMa。在处理大图的浏览查看动作过程中,往往还有其他额外的事情需要处理,典型的以微信。https://blog.csdn.net/zhangphil/article/details/131296499

Android RecyclerView AsyncListUtil手动刷新fillData,kotlin_zhangphil的博客-CSDN博客基于Android官方Paging Library的RecyclerView分页加载框架我之前写了一篇RecyclerView分页加载机制的文章,是基于Android官方的AsyncListUtil实现的,详情见附录文章1。基于Android官方Paging Library的RecyclerView分页加载框架我之前写了一篇RecyclerView分页加载机制的文章,是基于Android官方的AsyncListUtil实现的,详情见附录文章1。【代码】Android Paging 3,kotlin(1)https://blog.csdn.net/zhangphil/article/details/131519811

 

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

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

相关文章

Kafka的保姆级简易安装启动、关闭注意事项、简单使用

一.安装&#xff1a; 1.1Windows本机tar包安装 1.下载tar包 地址&#xff1a;Apache Download Mirrors&#xff0c;点击下面的连接先将tar包下载下来 2.解压到任意地址但自己要记得位置 3.进入到config文件找到server.properties更改信息 搜索&#xff0c;然后找到下面的地…

基于Spring Boot的广告公司业务管理平台设计与实现(Java+spring boot+MySQL)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于Spring Boot的广告公司业务管理平台设计与实现&#xff08;Javaspring bootMySQL&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 后端&#xff1a;Java springboot框架 …

开放式耳机推荐:开放式耳机是什么意思?开放式耳机的优缺点?开放式哪个品牌更好?韶音、南卡、cleer、索尼、飞利浦等开放式蓝牙耳机大盘点!

前言 要说目前可以让运动、工作变得更加轻松的单品&#xff0c;开放式蓝牙耳机绝对要占一席之地。开放式蓝牙耳机近年来的销量不断攀升&#xff0c;已经超越普通蓝牙耳机成为数码类销量抢手的产品&#xff0c;并且升级迭代速度很快&#xff0c;功能越来越完善&#xff0c;相比…

unity3d 入门1

新建一个3D core项目&#xff1b; 自动新建一个示例场景&#xff0c;仅包含2个对象&#xff0c;一个主摄像机&#xff0c;一个方向光&#xff1b;在Hierarchy层次视图中看到如下&#xff1b;场景使用一个小立方体来表示&#xff0c;下面的对象也使用一个小立方体 表示&#xf…

【通览一百个大模型】UL2(Google)

【通览一百个大模型】UL2&#xff08;Google&#xff09; 作者&#xff1a;王嘉宁&#xff0c;本文章内容为转载或整理&#xff0c;仓库链接&#xff1a;https://github.com/wjn1996/LLMs-NLP-Algo 订阅专栏【大模型&NLP&算法】可获得博主多年积累的全部NLP、大模型和算…

SLAM在ARM上的加速(3)- Neon在SLAM中的应用

SLAM在ARM上的加速&#xff1a; SLAM在ARM上的加速&#xff08;1&#xff09;- ARM加速基础 SLAM在ARM上的加速&#xff08;2&#xff09;- Neon SLAM在ARM上的加速&#xff08;3&#xff09;- Neon在SLAM中的应用 视觉SLAM通常可以分为前端和后端两个部分&#xff1a; (1)…

【深度学习】受限玻尔兹曼机 (RBM) 初学者指南

一、说明 受限玻尔兹曼机&#xff08;Restricted Boltzmann Machine&#xff0c;RBM&#xff09;是一种基于能量模型的人工神经网络。它只有一个隐层&#xff0c;将输入层和隐层中的每个神经元互相连接&#xff0c;但不同层的神经元之间没有连接。RBM是一种无向的概率图模型&am…

09_Linux内核定时器

目录 Linux时间管理和内核定时器简介 内核定时器简介 Linux内核短延时函数 定时器驱动程序编写 编写测试APP 运行测试 Linux时间管理和内核定时器简介 学习过UCOS或FreeRTOS的同学应该知道, UCOS或FreeRTOS是需要一个硬件定时器提供系统时钟,一般使用Systick作为系统时钟…

Vue生态及实践 - 优化实践

目录 目标 keep alive util/vue.js【vue里面常用的函数】 src/components/UKeepAlive.vue 无限加载列表优化的实现方案 src/util/throttle.js src/components/UInfiniteList.vue src/module/topic/views/UTopic.vue 献上一张ai生成图~ 目标 Keep Alive实践长列表优化…

基于pytorch的神经网络与对比学习CL的训练示例实战和代码解析

目录 对比学习原理解析构建一个对比学习模型&#xff08;代码详解&#xff09;导入库构建简单的神经网络构建对比学习的损失函数开始训练 完整代码 对比学习原理解析 对比学习&#xff08;Contrastive Learning&#xff09;是一种无监督学习方法&#xff0c;用于从未标记的数据…

3 STM32标准库函数 之 窗口看门狗(WWDG)所有函数的介绍及使用

3 STM32标准库函数 之 窗口看门狗&#xff08;WWDG&#xff09;所有函数的介绍及使用 1. 图片有格式2 文字无格式三 库函数之窗口看门狗&#xff08;WWDG&#xff09;所有函数的介绍及使用前言一、IWDG库函数固件库函数预览1.1 函 数 IWDG_WriteAccessCmd1.1.1 IWDG_WriteAcces…

string模拟实现

文章目录 1.回顾库函数strcpymemcpystrcmpstrstr 2.回顾类和对象哪些函数里会有this指针&#xff1f;this指针调用方法结论&#xff1a;只要是不修改this指针指向的对象内容的成员函数&#xff0c;都可以加上const自己写了构造函数&#xff0c;编译器不会自动生成默认构造2.1构…

代码随想录第21天 | 回溯理论基础 77. 组合

回溯理论基础 回溯法解决的问题都可以抽象为树形结构&#xff0c;是的&#xff0c;我指的是所有回溯法的问题都可以抽象为树形结构&#xff01; 因为回溯法解决的都是在集合中递归查找子集&#xff0c;集合的大小就构成了树的宽度&#xff0c;递归的深度&#xff0c;都构成的…

MySQL面试题总结(部分)

一.介绍MySQL为什么在面试中会提及 1.为什么要在面试时MySQL会被提及&#xff1f; 在面试中问MySQL问题有几个主要原因&#xff1a; 1. 数据库管理系统的重要性&#xff1a;MySQL作为一种常用的关系型数据库管理系统(RDBMS)&#xff0c;在互联网和企业应用中得到广泛使用。对数…

Conda安装及使用方法(常用命令)

系列文章目录 文章目录 系列文章目录前言一、Conda下载安装1.下载2.安装3.配置国内源 二、Conda安装Python环境1.创建虚拟环境2.激活虚拟环境3.虚拟环境安装Python库 三、Conda环境环境执行脚本四、PyCharm配置Conda环境五、Conda迁移环境1.方式一&#xff1a;拷贝环境2.方式二…

Modbus通信从入门到精通_1_Modbus通信基础

关于Modbus通信的相关知识比较零碎&#xff0c;此处对查找到的知识点从理论&#xff0c;通信协议、使用方法方面进行整理。 值得学习的博文&#xff1a;Modbus及调试用软件介绍&#xff1b;Modbus协议和上位机应用开发介绍 文章目录 1. Modbus通信理论1.1 Modbus通信特点1.2 存…

多线程(1): 线程的创建、回收、分离

1. 多线程概述 多线程在项目开发过程中使用频率非常高&#xff0c;因为使用多线程可以提高程序的并发性。提高程序并发性有两种方式:(1)多线程 (2)多进程。但是多线程对系统资源的消耗会更加少一些&#xff0c;并且线程和进程执行效率差不多。 在执行系统应用程序时&#xff…

2023/7/8总结

Tomcat 启动&#xff1a;双击bin目录下的startup.bat文件停止&#xff1a;双击bin目录下的shutdown.bat 文件访问 &#xff1a;http://localhost:8080&#xff08;默认是8080&#xff0c;可以修改&#xff09; git的使用 打开git bash git config --global user.name "名…

Vue3---什么是路由缓存问题

使用带有参数的路由时需要注意的是&#xff0c;当用户从 /users/johnny 导航到 /users/jolyne 时&#xff0c;相同的组件实例将被重复使用。因为两个路由都渲染同个组件&#xff0c;比起销毁再创建&#xff0c;复用则显得更加高效。不过&#xff0c;这也意味着组件的生命周期钩…

500万PV的网站需要多少台服务器?

1. 衡量业务量的指标 衡量业务量的指标项有很多&#xff0c;比如&#xff0c;常见Web类应用中的PV、UV、IP。而比较贴近业务的指标项就是大家通常所说的业务用户数。但这个用户数比较笼统&#xff0c;其实和真实访问量有比较大的差距&#xff0c;所以为了更贴近实际业务量及压力…