浅谈QFramework框架中的资源加载模块

本文详细介绍了QF框架中的异步资源加载机制,包括如何使用对象池分配资源加载器,如何通过两步操作加入加载队列,以及资源加载流程的详细步骤。作者还揭示了底层设计的巧妙之处,展示了如何通过Asset字段获取已加载资源。
摘要由CSDN通过智能技术生成

前言

之前在写个人小demo时,本来打算自己尝试实现资源加载模块,但是经过一段时间的尝试之后,发现自己还是能力有限,没办法处理稍微复杂一点的资源加载,于是就找到了QF框架,学习了一下它的使用,并且尝试阅读了它的实现逻辑和源码。

由于我主要学习和使用的是异步加载,所以在下面的讨论中,涉及到的是QF框架中的异步加载资源的部分。

模块简介

QF框架中的异步加载,使用起来非常的方便简洁,只需要从资源加载器对象池中获取资源加载器,然后通过两个步骤就可以完成动态的异步加载资源。下面贴一下我使用的例子

分配对象池

然后调用加入加载队列方法,这个放入加载队列的方法可以有回调函数,用于完成加载之后的操作,也可以不写回调

队列加入完成之后,直接调用加载器的异步加载方法

资源加载流程

整个资源加载流程,主要分为两个部分。第一个部分是把需要加载的资源加入加载队列,第二部分是对加载队列中的资源进行加载

加入加载队列

首先通过资源路径得到一个资源路径信息相关的对象,这个对象是从对象池中获取的,分配到的对象中,设置了必要的资源信息

分配好资源路径对象之后,进行把其加入加载队列的操作。这个操作分为三部分。

首先,先在需要在加载列表中查找是否已经把该资源放入过加载队列中,如果有,就可以直接获取这个资源对象(这个list不同于实际上的等待加载队列,这个队列应该是用于标记资源是否加入过等待加载队列)

没有的话,则需要创建一个对应的对象

创建完成后,需要对资源的依赖进行对应的操作,即分配资源对象以及加入查找其引用

在对资源依赖引用的处理中,框架中使用的是递归处理,对于每一层的依赖,都使用递归完全找出依赖资源,从而把所有需要加载的资源都加入到等待加载的队列中

具体的加入队列的操作方法中,实际上也没有特别复杂的事情,还是做一些必要的检查,然后根据传递的lastOder参数来决定从头部插入还是尾部插入

mWaitingLoadList是非常重要的队列,后续加载资源的操作,也是通过这个list来进行的。所以,lastOder参数同时也可以决定资源加载的顺序,在有些情况下,比如某些场景中的某些资源需要优先加载,这种参数显得尤为重要。

还有一个比较巧妙的点,在资源加入队列的过程中,对当前加载器的等待加载数量进行计算。这个操作可以在实际加载时用上。

需要加载的资源全部放入等待加载的队列中后,只需要启动异步加载,等待队列中的资源全部加载完毕即可。

资源加载操作

资源加载操作的启动非常的简单,就直接调用资源加载器的异步加载方法即可。

加载方法的内容非常简单,但是里面的处理,还是有一些巧妙之处的

在真正调用资源实例自身的加载方法之前,还需要做一些处理。在具体说明DoLoadAsync方法中的操作之前,我们需要先对之前加入等待加载队列的res实例进行一定的了解

res实例是基于IRes接口实例化的对象,它的内部有几个重要的属性和方法

查找代码的源头,我们能看到IRes接口中声明的属性成员和提前预设的方法,其中AssetName,OwnerBundleName,AssetType都是该资源相关的信息,Asset是实际的资源,资源加载后用于存储Object的属性,还有一些对回调方法的触发事件,还有非常关键的标记属性State以及真正的加载方法LoadAsync

这个res就是之前加入等待加载队列的具体实例,对它有一定的了解之后,我们再来看加载之前的最后处理

首先检查是否还有需要加载的对象,这个可以通过之前加入队列时做的计数直接判断,不需要去遍历等待加载的队列。当等待加载的数量为0时,说明加载完毕,那么只需要做最后的操作,即加载完毕资源后触发对应的回调函数即可。

然后采用单链表的方式逐个取出等待列表中的加载对象,先加载其依赖资源,然后确认该资源的状态,注册好回调方法触发事件之后,进行真正的资源加载操作。

真正的资源加载操作中,处理的方法也非常巧妙

修改完状态之后,把需要加载的资源自身,放入了加载资源的task队列中,然后再启动协程开启task的异步加载方法

到此,整个的异步加载流程就完成了,剩下的就是触发回调方法来具体操作得到的资源对象,或者保存加载的资源之后自行操作。

整体总结

整个资源加载的模块是非常清晰,也是独立的模块。总共分为两个步骤,其一是把需要加载的资源对应的对象实例创建出来,并且做好一系列相关的准备工作,然后把其加入等待加载的列表;其二是用协程把等待加载的列表中的所有资源对象加载出来,加载的方式就是通过资源对象自身的路径信息,启动自身带有的加载方法来实现实际的加载。

实际上,在创建资源对象实例的时候,底层做了非常多的巧妙设计,我在阅读源码时,也是通过调试反复阅读才慢慢感受到其中的设计思想。由于内容的篇幅有限,我只挑选部分比较能体现设计思想的地方稍微解析一下,这也是我印象比较深刻的困惑之一。

在前文的解析中,我们看到了真正的资源加载的地方,实际上是在res对象中自己的DoLoadAsync方法中执行的,并且执行的是一个协程,达到了异步非阻塞的目的

实际的加载操作也非常的简单,寥寥数行就完成了加载的操作

但是,如果你还记得开头的调用加载队列的回调函数中具体获取到加载好的资源的属性值,就会发现,那个属性值和上图中的AssetBundle实际上不是同一个属性字段。

那它是如何通过Asset字段获取到保存的已经加载的资源的呢?想知道这个问题的答案,我们需要知道这两个不同属性字段里存的到底是什么。

首先看看AssetBundle字段中到底做了什么

这个操作实际上就是把获取的值赋给mAsset,而mAsset是基类Res中继承来的属性

而Asset属性字段,也是基类Res的属性字段

那么到这我们就知道了,实际上保存的操作,在底层设计时就已经处理好了,在自己的类方法中处理好赋值操作,然后通过暴露给外部的Asset属性获取到。

而这个类AssetBundleRes本身就是继承于Res基类的,在基类中就已经做好了暴露属性的预操作以及保存的私有属性

在创建res对象实例时,就是从AssetBundleRes对象池中分配的AssetBundleRes对象

结语

对于QF框架中的异步加载模块的探讨,暂时就告一段落。在反复调试以及阅读底层源码的过程中,逐渐感受到设计中的巧妙之处,从而搞清楚流程。刚开始的时候,阅读源码是非常痛苦的,但是当你能够逐渐梳理出逻辑性时,就能感觉到真正的妙处。希望今后阅读不同的代码,也能保持这样的心态,逐渐成长,愿你我有一天,能够顶峰相见!

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值