在我们可以通过assets的方式加在pag文件之后,我们会考虑下一个问题,可不可以用Pag框架加载网络文件?
为什么会有这样的问题出现,或者说网络方式加载可以解决什么问题?
-
APK 体积增加问题
当一个项目规模比较大的时候,会做很多优化工作,其中「APK瘦身」便是一项优化点。通过网络的方式加载可以减少内置文件,从而降低APK大小。
-
热更新问题
我们有时候是有这样的需求的,线上更改动画效果,通过网络方式便可以做到。
-
新的功能或者组件上线,需要更新客户端问题。
在某些功能中,比如我们现有的图片列表类的,只要线上的api返回新的图片地址即可;那么对于pag,我们也想要有这样的效果。
and more……
有了以上的问题,我们决定做「网络加载Pag」功能!
一、做网络加载Pag需要考虑什么?(其实是所有的网络加载需要考虑的事情)
1、下载器
网络加载的第一步肯定是下载,那么选择一个合适的下载器是十分重要的,这个下载器最好支持什么功能?
-
多线程下载(同时需要服务端支持,下载时可指定range)
-
断点续传
-
通用性(其他位置也可以)
-
任务队列(任务优先级等)
-
暂停、继续
-
下载失败文件处理
2、缓存策略
我们熟知的缓存策略可能就是Glide中的图片三级缓存策略了。其实不止图片,所有的缓存策略基本上就是这三级:
1、 内存缓存
2、磁盘缓存
3、网络(严格意义上来讲,这不算是个缓存)
既然是缓存,就需要考虑缓存的清理策略。我们熟知有的LruCache、DiskLruCache。根据项目的实际情况选择即可。
3、文件校验
为什么需要文件校验,其实有很多原因。但大多数无外乎以下几种:
-
文件完整性。我们加载损坏的文件,肯定是展示不出内容的。除非只损换了padding,也就是字节填充部分的内容
-
文件安全性。我们的文件如果中途被人篡改,我们可以通过此种方式来校验安全性。当然安全性校验一般会通过MD5、SHA256等哈希算法进行校验,会增加读取文件耗时。
-
文件校验失败后的重新下载。一般文件校验失败了,也就证明当前缓存是有问题的,或者中间被人篡改了。这时根据当前文件是缓存还是直接下载的文件,去做对应的处理。如果是缓存文件,会直接删除重新下载,如果非缓存文件,可能提示出错等。
二、Pag文件网络加载具体怎么做?
先说明:如果你使用的是4.3.3版本(包含)后的pag,它的sdk已经内置了网络加载功能,可以直接指定一个url地址的。
当然如果你的项目中需要统一处理缓存,统一下载,或者已经有了成熟的下载器框架。就需要自己搭建一个Pag网络加载方案了。
1、使用Glide加载?
我第一步的考虑是能否通过扩展Glide来增加对Pag文件的支持,为什么会这么考虑,因为Glide已经支持了三级缓存功能,我没必要再实现一次。Glide也有下载功能,我没有必要再实现一次。
我也去网上查了,确实有这样的方案的。但是后来我没采用。原因有下:
-
新的Pag文件缓存会占用Glide中配置的缓存空间大小,会影响原本图片缓存。
-
项目内部已经有了针对项目的缓存策略,如果使用Glide会打乱原有非图片文件的缓存策略,不方便统一管理。
-
现有的下载器,支持多线程下载,可以提升大文件下载速度。
2、新创建加载Pag框架。
后面还是决定自己Pag。基本的流程是这样。
-
根据Url的MD5判断本地是否有缓存。
-
有缓存
-
校验缓存是否完整(没有做安全性校验,因为这个动画文件,感觉没必要)。自己根据Pag文件的格式写了一个校验工具。(后来发现没卵用,给删除了)
-
若完整,直接加载
-
若加载失败,重新下载。
-
-
无缓存
-
下载器下载
-
下载成功后,PagFile.load()。
-
打完收工,基本上我测试了一下没啥问题。
源码就不上了,只要是思路比较重要。
遇到的问题
我不是自己写了个校验工具,我为啥写了个校验工具呢?因为我调用PagFile.load方法发现,返回的是非空的类型(它的代码中没有标记@NonNull),于是我认为即使它加载错了,也会返回一个非空对象,那我何不自己先校验一下。于是翻Pag的源码,根据它内部的校验规则,我先提前一步校验了。
结果问题出现了,有一个损坏了的文件,通过了我的校验工具检验,但是没加载出来,并在Log中看到了 Invild File。
后来我发现,因为PagFile的代码是java代码,而且没有被@Nonnull标记,而我们项目中用的是Kotlin,这样会导致一个什么问题,Kotlin认为该文件是非空的。
于是查阅pag源码,发现在C层的代码里,当加载文件失败时(这个过程会走文件校验),会直接返回一个nullptr,也就是空指针。于是我将自己的校验工具去掉了,直接判断Load的结果,如果是空则证明加载失败了,而加载失败的最大可能就是,文件错了,此时走重新下载,或者其他处理即可。文章来源:https://www.toymoban.com/news/detail-643990.html
伪代码:文章来源地址https://www.toymoban.com/news/detail-643990.html
val result = PAGFile.Load(file.path)
if (result == null) { downloadIt() }
else { pagView.componsition = result }
到了这里,关于腾讯出品Pag动画框架在Android端的使用-网络Pag加载的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!