span从入门到精通1 第三方工具类GifDrawable

2024-05-29 00:32

本文主要是介绍span从入门到精通1 第三方工具类GifDrawable,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

好久没有写博客了这次介绍下span的使用希望大家少走弯路这次我们从工具类GifDrawable说起
先看基本效果图吧
这里写图片描述

大家看不太懂不要慌我会把代码传到GitHub上后面会附带GitHub链接

首先先看基本的使用然后再逐步分析

GifDrawable gifDrawable = new RefreshGifDrawable(getResources(), R.drawable.a);
GlidePreDrawable glidePreDrawable = new GlideReusePreDrawable();
GlideApp.with(this).load("http://5b0988e595225.cdn.sohucs.com/images/20170919/1ce5d4c52c24432e9304ef942b764d37.gif").placeholder(gifDrawable).into(new DrawableTarget(glidePreDrawable));
CharSequence charSequence = DrawableUtil.getDrawableText("[c]", glidePreDrawable);
spEditText.insertSpecialStr(charSequence, false, charSequence, null);

里面有几个关键的元素GifDrawable ,RefreshGifDrawable,DrawableTarget,spEditText在接下来的过程里我们会对这几个类做着重介绍。

由于全面介绍可能大家,看起来会头疼这里我们针对使用流程进行分析。
首先我们来看new RefreshGifDrawable(getResources(), R.drawable.a)这个东西是什么东东都有哪些处理(前提声明 R.drawable.a是一个gif图片)
代码如下

    public RefreshGifDrawable(@NonNull Resources res,int id) throws Resources.NotFoundException, IOException {super(res, id);}

很简单吧我们再看他这个super做了些什么

public GifDrawable(@NonNull Resources res, @RawRes @DrawableRes int id) throws NotFoundException, IOException {this(res.openRawResourceFd(id));final float densityScale = GifViewUtils.getDensityScale(res, id);mScaledHeight = (int) (mNativeInfoHandle.getHeight() * densityScale);mScaledWidth = (int) (mNativeInfoHandle.getWidth() * densityScale);}

我们先从this(res.openRawResourceFd(id));这里看起res.openRawResourceFd(id)是Android系统处理将我们的gif当成二进制对象处理返回AssetFileDescriptor这个对象我们再看this的处理

public GifDrawable(@NonNull AssetFileDescriptor afd) throws IOException {this(new GifInfoHandle(afd), null, null, true);}

这里new了一个GifInfoHandle我们再看GifInfoHandle都做了些什么好我们继续看他的构造处理

GifInfoHandle(AssetFileDescriptor afd) throws IOException {try {gifInfoPtr = openFd(afd.getFileDescriptor(), afd.getStartOffset());} finally {try {afd.close();} catch (IOException ignored) {//no-op}}}

通过这里我们看到他调用了openFd方法并返回gifInfoPtr 最终关闭afd流释放资源接下来我们需要分析openFd方法(感觉这个可能是核心处理之一)我们接下来继续看

static native long openFd(FileDescriptor fd, long offset) throws GifIOException;

擦这居然是个jni方法好吧做到这里我们只能看其他地方了,我们在看他的返回值

    /*** Pointer to native structure. Access must be synchronized, heap corruption may occur otherwise* when {@link #recycle()} is called during another operation.*/private volatile long gifInfoPtr;

大致意思是返回的是一个指向native的一个底层指针,我们再捋一遍这个流程,将我们的res文件转换成二进制解析对象在经过处理返回一个底层指针。我们再回去继续看。

public GifDrawable(@NonNull AssetFileDescriptor afd) throws IOException {this(new GifInfoHandle(afd), null, null, true);}

我们再继续分析下这个this又调的什么处理(注意这里可能是初始化的关键点)

GifDrawable(GifInfoHandle gifInfoHandle, final GifDrawable oldDrawable, ScheduledThreadPoolExecutor executor, boolean isRenderingTriggeredOnDraw) {mIsRenderingTriggeredOnDraw = isRenderingTriggeredOnDraw;mExecutor = executor != null ? executor : GifRenderingExecutor.getInstance();mNativeInfoHandle = gifInfoHandle;Bitmap oldBitmap = null;if (oldDrawable != null) {synchronized (oldDrawable.mNativeInfoHandle) {if (!oldDrawable.mNativeInfoHandle.isRecycled()&& oldDrawable.mNativeInfoHandle.getHeight() >= mNativeInfoHandle.getHeight()&& oldDrawable.mNativeInfoHandle.getWidth() >= mNativeInfoHandle.getWidth()) {oldDrawable.shutdown();oldBitmap = oldDrawable.mBuffer;oldBitmap.eraseColor(Color.TRANSPARENT);}}}if (oldBitmap == null) {mBuffer = Bitmap.createBitmap(mNativeInfoHandle.getWidth(), mNativeInfoHandle.getHeight(), Bitmap.Config.ARGB_8888);} else {mBuffer = oldBitmap;}mBuffer.setHasAlpha(!gifInfoHandle.isOpaque());mSrcRect = new Rect(0, 0, mNativeInfoHandle.getWidth(), mNativeInfoHandle.getHeight());mInvalidationHandler = new InvalidationHandler(this);mRenderTask.doWork();mScaledWidth = mNativeInfoHandle.getWidth();mScaledHeight = mNativeInfoHandle.getHeight();}

第一行给mIsRenderingTriggeredOnDraw赋值根据前面传过来的值为true即我们再绘制时需要触发渲染(这个目前还没用到)
第二行初始化mExecutor传入值为空为默认渲染线程池
第三行处理mNativeInfoHandle = gifInfoHandle;给底层处理赋值
oldDrawable为空不执行(假如为空里面的处理大致意思就是如果回收了重置bitmap的资源)

if (oldBitmap == null) {mBuffer = Bitmap.createBitmap(mNativeInfoHandle.getWidth(), mNativeInfoHandle.getHeight(), Bitmap.Config.ARGB_8888);} else {mBuffer = oldBitmap;}

这块儿的处理就是根据底层类提供的指针获取图片的宽高并以ARGB_8888的方式加载获取一个bitmap对象。
setHasAlpha(boolean hasAlpha) 这一块的处理是判断是否有alpha如果图片是不透明的画的更快些。
接下来处理初始化mSrcRect确定图片的外切矩形
初始化mInvalidationHandler
执行mRenderTask
初始化mScaledWidth mScaledHeight
最后执行下面代码

final float densityScale = GifViewUtils.getDensityScale(res, id);
mScaledHeight = (int) (mNativeInfoHandle.getHeight() * densityScale);
mScaledWidth = (int) (mNativeInfoHandle.getWidth() * densityScale);

好到了这里我们确认下初始化的内容
1.初始化了常量mIsRenderingTriggeredOnDraw即在绘制时需要触发渲染
2.初始化mExecutor 执行渲染的线程池
3.初始化获取底层处理对象mNativeInfoHandle通过指针获取底层gif的内容
4.初始化Bitmap对象mBuffer
5.初始化mSrcRect确定图像外围
6.初始化mInvalidationHandler
7.执行mRenderTask
8.初始化mScaledWidth, mScaledHeight这里后面还要根据屏幕密度resize宽高
到这里我们解析gif所需要的工具 应该都齐了接下来我们继续往下看

我们再看下面
GifDrawable gifDrawable = new RefreshGifDrawable(getResources().getAssets(), “timg.gif”)
这里的处理给上面差不多这里我就不再过多说明了
做到这里我们在执行下下面的方法
GlideApp.with(this).load(gifDrawable)
// .diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(d1).into(new DrawableTarget(glidePreDrawable));

如果这个target是一个ImageView的话我们将会将这个gif图设置到ImageView中去这样的话我们的操作就结束了 ,我会在下一篇文章中对这些内容进行更细致的分析,祝大家生活愉快。

gitHub链接点击这里

这篇关于span从入门到精通1 第三方工具类GifDrawable的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

python版本切换工具pyenv的安装及用法

《python版本切换工具pyenv的安装及用法》Pyenv是管理Python版本的最佳工具之一,特别适合开发者和需要切换多个Python版本的用户,:本文主要介绍python版本切换工具pyen... 目录Pyenv 是什么?安装 Pyenv(MACOS)使用 Homebrew:配置 shell(zsh

Python+wxPython开发一个文件属性比对工具

《Python+wxPython开发一个文件属性比对工具》在日常的文件管理工作中,我们经常会遇到同一个文件存在多个版本,或者需要验证备份文件与源文件是否一致,下面我们就来看看如何使用wxPython模... 目录引言项目背景与需求应用场景核心需求运行结果技术选型程序设计界面布局核心功能模块关键代码解析文件大

SpringCloud Stream 快速入门实例教程

《SpringCloudStream快速入门实例教程》本文介绍了SpringCloudStream(SCS)组件在分布式系统中的作用,以及如何集成到SpringBoot项目中,通过SCS,可... 目录1.SCS 组件的出现的背景和作用2.SCS 集成srping Boot项目3.Yml 配置4.Sprin

SpringMVC配置、映射与参数处理​入门案例详解

《SpringMVC配置、映射与参数处理​入门案例详解》文章介绍了SpringMVC框架的基本概念和使用方法,包括如何配置和编写Controller、设置请求映射规则、使用RestFul风格、获取请求... 目录1.SpringMVC概述2.入门案例①导入相关依赖②配置web.XML③配置SpringMVC

MySQL索引踩坑合集从入门到精通

《MySQL索引踩坑合集从入门到精通》本文详细介绍了MySQL索引的使用,包括索引的类型、创建、使用、优化技巧及最佳实践,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录mysql索引完整教程:从入门到入土(附实战踩坑指南)一、索引是什么?为什么需要它?1.1 什么

Java Lettuce 客户端入门到生产的实现步骤

《JavaLettuce客户端入门到生产的实现步骤》本文主要介绍了JavaLettuce客户端入门到生产的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录1 安装依赖MavenGradle2 最小化连接示例3 核心特性速览4 生产环境配置建议5 常见问题

基于Python开发Windows自动更新控制工具

《基于Python开发Windows自动更新控制工具》在当今数字化时代,操作系统更新已成为计算机维护的重要组成部分,本文介绍一款基于Python和PyQt5的Windows自动更新控制工具,有需要的可... 目录设计原理与技术实现系统架构概述数学建模工具界面完整代码实现技术深度分析多层级控制理论服务层控制注

使用Go调用第三方API的方法详解

《使用Go调用第三方API的方法详解》在现代应用开发中,调用第三方API是非常常见的场景,比如获取天气预报、翻译文本、发送短信等,Go作为一门高效并发的编程语言,拥有强大的标准库和丰富的第三方库,可以... 目录引言一、准备工作二、案例1:调用天气查询 API1. 注册并获取 API Key2. 代码实现3

基于Go语言开发一个 IP 归属地查询接口工具

《基于Go语言开发一个IP归属地查询接口工具》在日常开发中,IP地址归属地查询是一个常见需求,本文将带大家使用Go语言快速开发一个IP归属地查询接口服务,有需要的小伙伴可以了解下... 目录功能目标技术栈项目结构核心代码(main.go)使用方法扩展功能总结在日常开发中,IP 地址归属地查询是一个常见需求:

使用python制作一款文件粉碎工具

《使用python制作一款文件粉碎工具》这篇文章主要为大家详细介绍了如何使用python制作一款文件粉碎工具,能够有效粉碎密码文件和机密Excel表格等,感兴趣的小伙伴可以了解一下... 文件粉碎工具:适用于粉碎密码文件和机密的escel表格等等,主要作用就是防止 别人用数据恢复大师把你刚删除的机密的文件恢