UFL5-6——AB包资源管理器的异步加载修改

管理器代码继承自:UH1L4——AB包资源管理器

重新按照ABMgr中的规则进行AB包打包

image

ABMgr异步加载修改主要目标

将ABMgr中的异步加载方法彻底异步化,让其中的依赖包加载、资源包加载、资源加载都变为异步加载

注意:主包可以保留同步加载

需要考虑的主要问题

  1. 某个AB包当正在异步加载时又进行重复加载,遇到这种情况时,我们需要避免重复加载报错
    因此我们不应再次加载,而是等待之前的异步加载结束后直接使用

    首先将同步加载AB包的方法LoadAB​进行拆分,将加载主包的逻辑提取出来,新声明一个LoadMainAB​去实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    private void LoadMainAB()
    {
    //加载主包
    if (mainAB == null)
    {
    mainAB = AssetBundle.LoadFromFile(PathUrl + MainABName);
    manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    }
    }

    public void LoadAB(string abName)
    {
    LoadMainAB();
    //获取依赖包相关信息
    AssetBundle ab;
    //加载主包中的关键配置文件 获取依赖包
    string[] strs = manifest.GetAllDependencies(abName);
    //加载依赖包
    for (int i = 0; i < strs.Length; i++)
    {
    //判断包是否加载过
    if (!abDic.ContainsKey(strs[i]))
    {
    ab = AssetBundle.LoadFromFile(PathUrl + strs[i]);
    abDic.Add(strs[i], ab);
    }
    }
    //加载目标包
    if (!abDic.ContainsKey(abName))
    {
    ab = AssetBundle.LoadFromFile(PathUrl + abName);
    abDic.Add(abName, ab);
    }
    }

    然后将原来协程内的异步加载协程方法内调用LoadAB​的部分都替换掉,转为实现新的逻辑

    1. 同步加载主包

    2. 获取依赖包

    3. 循环加载依赖包

      1. 如果字典内不存在记录,说明没有加载过

        1. 加载前就往字典内添加记录,值传入null​,然后异步加载AB包,直到加载完毕后才向字典内对应的记录赋值,关联加载出来的AB包
      2. 字典内存在记录,说明AB包正在异步加载或者加载已经结束了

        1. 如果字典内对应的记录值为空,说明正在加载,此时就循环挂起一帧协程,直到发现记录内关联了AB包
    4. 加载目标包

      1. 如果字典内不存在记录,说明没有加载过

        1. 加载前就往字典内添加记录,值传入null​,然后异步加载AB包,直到加载完毕后才向字典内对应的记录赋值,关联加载出来的AB包
      2. 字典内存在记录,说明AB包正在异步加载或者加载已经结束了

        1. 如果字典内对应的记录值为空,说明正在加载,此时就循环挂起一帧协程,直到发现记录内关联了AB包
    5. 从目标包内加载异步资源,将加载出来的资源传入到回调函数内执行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    private IEnumerator LoadResCoroutine<T>(string abName, string resName, UnityAction<T> callBack) where T : Object
    {
    //加载AB包
    LoadMainAB();
    //加载主包中的关键配置文件 获取依赖包
    string[] strs = manifest.GetAllDependencies(abName);
    //加载依赖包
    for (int i = 0; i < strs.Length; i++)
    {
    //判断包是否加载过
    if (!abDic.ContainsKey(strs[i]))
    {
    //一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
    abDic.Add(strs[i], null);
    AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + strs[i]);
    yield return req;
    //异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
    abDic[strs[i]] = req.assetBundle;
    }
    //字典存在记录,说明AB包正在异步加载或者加载已经结束了
    else
    {
    //如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
    while (abDic[strs[i]] == null)
    {
    //只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
    yield return 0;
    }
    }
    }
    //加载目标包
    if (!abDic.ContainsKey(abName))
    {
    //一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
    abDic.Add(abName, null);
    AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + abName);
    yield return req;
    //异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
    abDic[abName] = req.assetBundle;
    }
    //字典存在记录,说明AB包正在异步加载或者加载已经结束了
    else
    {
    //如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
    while (abDic[abName] == null)
    {
    //只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
    yield return 0;
    }
    }
    AssetBundleRequest abr = abDic[abName].LoadAssetAsync<T>(resName);
    yield return abr;

    //异步加载结束后,通过委托,传递给外部,来使用
    callBack(abr.asset as T);
    }

    其他的异步加载协程的重载也替换掉LoadAB​,换成新的异步加载AB包的逻辑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    private IEnumerator LoadResCoroutine(string abName, string resName, UnityAction<Object> callBack)
    {
    //加载AB包
    LoadMainAB();
    //加载主包中的关键配置文件 获取依赖包
    string[] strs = manifest.GetAllDependencies(abName);
    //加载依赖包
    for (int i = 0; i < strs.Length; i++)
    {
    //判断包是否加载过
    if (!abDic.ContainsKey(strs[i]))
    {
    //一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
    abDic.Add(strs[i], null);
    AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + strs[i]);
    yield return req;
    //异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
    abDic[strs[i]] = req.assetBundle;
    }
    //字典存在记录,说明AB包正在异步加载或者加载已经结束了
    else
    {
    //如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
    while (abDic[strs[i]] == null)
    {
    //只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
    yield return 0;
    }
    }
    }
    //加载目标包
    if (!abDic.ContainsKey(abName))
    {
    //一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
    abDic.Add(abName, null);
    AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + abName);
    yield return req;
    //异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
    abDic[abName] = req.assetBundle;
    }
    //字典存在记录,说明AB包正在异步加载或者加载已经结束了
    else
    {
    //如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
    while (abDic[abName] == null)
    {
    //只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
    yield return 0;
    }
    }
    AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName);
    yield return abr;
    //异步加载结束后,通过委托,传递给外部,来使用
    callBack(abr.asset);
    }

    private IEnumerator LoadResCoroutine(string abName, string resName, System.Type type, UnityAction<Object> callBack)
    {
    //加载AB包
    LoadMainAB();
    //加载主包中的关键配置文件 获取依赖包
    string[] strs = manifest.GetAllDependencies(abName);
    //加载依赖包
    for (int i = 0; i < strs.Length; i++)
    {
    //判断包是否加载过
    if (!abDic.ContainsKey(strs[i]))
    {
    //一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
    abDic.Add(strs[i], null);
    AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + strs[i]);
    yield return req;
    //异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
    abDic[strs[i]] = req.assetBundle;
    }
    //字典存在记录,说明AB包正在异步加载或者加载已经结束了
    else
    {
    //如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
    while (abDic[strs[i]] == null)
    {
    //只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
    yield return 0;
    }
    }
    }
    //加载目标包
    if (!abDic.ContainsKey(abName))
    {
    //一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
    abDic.Add(abName, null);
    AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + abName);
    yield return req;
    //异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
    abDic[abName] = req.assetBundle;
    }
    //字典存在记录,说明AB包正在异步加载或者加载已经结束了
    else
    {
    //如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
    while (abDic[abName] == null)
    {
    //只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
    yield return 0;
    }
    }
    AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName, type);
    yield return abr;
    //异步加载结束后,通过委托,传递给外部,来使用
    callBack(abr.asset);
    }
  2. 正在加载某个AB包时

    • 卸载AB包:如果正在加载中,不允许卸载

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      //单个包卸载
      public void UnLoad(string abName, UnityAction<bool> callBackResult)
      {
      if (abDic.ContainsKey(abName))
      {
      if (abDic[abName] == null)
      {
      //如果发现正在异步加载,则不允许卸载,向回调函数传入false
      callBackResult?.Invoke(false);
      return;
      }
      abDic[abName].Unload(false);
      abDic.Remove(abName);
      //卸载成功,向回调函数传入true
      callBackResult?.Invoke(true);
      }
      }
    • 清空AB包:停止所有协同程序,在清理AB包

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      //所有包的卸载
      public void ClearAB()
      {
      //由于AB包都是异步加载,同时停止所有的异步加载协程
      StopAllCoroutines();
      AssetBundle.UnloadAllAssetBundles(false);
      abDic.Clear();
      //卸载主包,卸载依赖文件
      mainAB = null;
      manifest = null;
      }

使用示例

两次异步加载同一包下的同一资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Main : MonoBehaviour
{
void Start()
{
ABManager.Instance.LoadResAsync<GameObject>("test", "Cube", (obj) =>
{
GameObject gameObj = Instantiate(obj);
gameObj.name = "ABMgrCreateObj";
});
ABManager.Instance.LoadResAsync<GameObject>("test", "Cube", (obj) =>
{
GameObject gameObj = Instantiate(obj);
gameObj.name = "ABMgrCreateObj";
});
}
}

输出:image

具体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// 通过AB包进行资源加载的管理器
/// </summary>
public class ABManager : SingletonAutoMono<ABManager>
{
//主包
private AssetBundle mainAB = null;
//依赖包获取用的配置文件
private AssetBundleManifest manifest = null;

private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();

/// <summary>
/// AB包存放路径,随项目修改
/// </summary>
private string PathUrl
{
get
{
return Application.streamingAssetsPath + "/";
}
}

private string MainABName
{
get
{
#if UNITY_IOS
return "IOS";
#elif UNITY_ANDROID
return "Android";
#else
return "PC";
#endif
}
}

#region 同步加载
private void LoadMainAB()
{
//加载主包
if (mainAB == null)
{
mainAB = AssetBundle.LoadFromFile(PathUrl + MainABName);
manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
}
}

public void LoadAB(string abName)
{
LoadMainAB();
//获取依赖包相关信息
AssetBundle ab;
//加载主包中的关键配置文件 获取依赖包
string[] strs = manifest.GetAllDependencies(abName);
//加载依赖包
for (int i = 0; i < strs.Length; i++)
{
//判断包是否加载过
if (!abDic.ContainsKey(strs[i]))
{
ab = AssetBundle.LoadFromFile(PathUrl + strs[i]);
abDic.Add(strs[i], ab);
}
}
//加载目标包
if (!abDic.ContainsKey(abName))
{
ab = AssetBundle.LoadFromFile(PathUrl + abName);
abDic.Add(abName, ab);
}
}

//同步加载,不指定类型
public Object LoadRes(string abName, string resName)
{
//加载AB包
LoadAB(abName);
Object obj = abDic[abName].LoadAsset(resName);
//为了外部使用方便,在加载资源时,先判断是否为Object,如果是直接实例化返回出去
if (obj is GameObject)
return Instantiate(obj);
else
return obj;
}

//同步加载,使用type指定类型
public Object LoadRes(string abName, string resName, System.Type type)
{
//加载AB包
LoadAB(abName);
Object obj = abDic[abName].LoadAsset(resName, type);
//为了外部使用方便,在加载资源时,先判断是否为Object,如果是直接实例化返回出去
if (obj is GameObject)
return Instantiate(obj);
else
return obj;
}

//同步加载,使用泛型指定类型
public T LoadRes<T>(string abName, string resName) where T : Object
{
//加载AB包
LoadAB(abName);
T obj = abDic[abName].LoadAsset<T>(resName);
//为了外部使用方便,在加载资源时,先判断是否为Object,如果是直接实例化返回出去
if (obj is GameObject)
return Instantiate(obj);
else
return obj;
}

#endregion

#region 异步加载
//这里的异步加载 AB包并没有使用异步加载,只是从AB包中加载资源时异步加载

//通过名字异步加载资源
public void LoadResAsync(string abName, string resName, UnityAction<Object> callBack)
{
StartCoroutine(LoadResCoroutine(abName, resName, callBack));
}

private IEnumerator LoadResCoroutine(string abName, string resName, UnityAction<Object> callBack)
{
//加载AB包
LoadMainAB();
//加载主包中的关键配置文件 获取依赖包
string[] strs = manifest.GetAllDependencies(abName);
//加载依赖包
for (int i = 0; i < strs.Length; i++)
{
//判断包是否加载过
if (!abDic.ContainsKey(strs[i]))
{
//一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
abDic.Add(strs[i], null);
AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + strs[i]);
yield return req;
//异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
abDic[strs[i]] = req.assetBundle;
}
//字典存在记录,说明AB包正在异步加载或者加载已经结束了
else
{
//如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
while (abDic[strs[i]] == null)
{
//只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
yield return 0;
}
}
}
//加载目标包
if (!abDic.ContainsKey(abName))
{
//一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
abDic.Add(abName, null);
AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + abName);
yield return req;
//异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
abDic[abName] = req.assetBundle;
}
//字典存在记录,说明AB包正在异步加载或者加载已经结束了
else
{
//如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
while (abDic[abName] == null)
{
//只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
yield return 0;
}
}
AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName);
yield return abr;
//异步加载结束后,通过委托,传递给外部,来使用
callBack(abr.asset);
}

//根据Type异步加载资源
public void LoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callBack)
{
StartCoroutine(LoadResCoroutine(abName, resName, type, callBack));
}

private IEnumerator LoadResCoroutine(string abName, string resName, System.Type type, UnityAction<Object> callBack)
{
//加载AB包
LoadMainAB();
//加载主包中的关键配置文件 获取依赖包
string[] strs = manifest.GetAllDependencies(abName);
//加载依赖包
for (int i = 0; i < strs.Length; i++)
{
//判断包是否加载过
if (!abDic.ContainsKey(strs[i]))
{
//一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
abDic.Add(strs[i], null);
AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + strs[i]);
yield return req;
//异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
abDic[strs[i]] = req.assetBundle;
}
//字典存在记录,说明AB包正在异步加载或者加载已经结束了
else
{
//如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
while (abDic[strs[i]] == null)
{
//只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
yield return 0;
}
}
}
//加载目标包
if (!abDic.ContainsKey(abName))
{
//一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
abDic.Add(abName, null);
AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + abName);
yield return req;
//异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
abDic[abName] = req.assetBundle;
}
//字典存在记录,说明AB包正在异步加载或者加载已经结束了
else
{
//如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
while (abDic[abName] == null)
{
//只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
yield return 0;
}
}
AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName, type);
yield return abr;
//异步加载结束后,通过委托,传递给外部,来使用
callBack(abr.asset);
}

//根据泛型异步加载
public void LoadResAsync<T>(string abName, string resName, UnityAction<T> callBack) where T : Object
{
StartCoroutine(LoadResCoroutine(abName, resName, callBack));
}

private IEnumerator LoadResCoroutine<T>(string abName, string resName, UnityAction<T> callBack) where T : Object
{
//加载AB包
LoadMainAB();
//加载主包中的关键配置文件 获取依赖包
string[] strs = manifest.GetAllDependencies(abName);
//加载依赖包
for (int i = 0; i < strs.Length; i++)
{
//判断包是否加载过
if (!abDic.ContainsKey(strs[i]))
{
//一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
abDic.Add(strs[i], null);
AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + strs[i]);
yield return req;
//异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
abDic[strs[i]] = req.assetBundle;
}
//字典存在记录,说明AB包正在异步加载或者加载已经结束了
else
{
//如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
while (abDic[strs[i]] == null)
{
//只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
yield return 0;
}
}
}
//加载目标包
if (!abDic.ContainsKey(abName))
{
//一开始异步加载就记录,如果此时的记录的AB包为空,说明该AB包正在异步加载
abDic.Add(abName, null);
AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(PathUrl + abName);
yield return req;
//异步加载结束后再替换以前的null,此时记录的AB包不为null,证明加载结束了
abDic[abName] = req.assetBundle;
}
//字典存在记录,说明AB包正在异步加载或者加载已经结束了
else
{
//如果字典中记录的消息是null,则证明正在加载中,这时就需要等待加载结束
while (abDic[abName] == null)
{
//只要发现正在加载中,就不停的等待一帧,下一帧再进行判断
yield return 0;
}
}
AssetBundleRequest abr = abDic[abName].LoadAssetAsync<T>(resName);
yield return abr;

//异步加载结束后,通过委托,传递给外部,来使用
callBack(abr.asset as T);
}
#endregion

//单个包卸载
public void UnLoad(string abName, UnityAction<bool> callBackResult)
{
if (abDic.ContainsKey(abName))
{
if (abDic[abName] == null)
{
//如果发现正在异步加载,则不允许卸载,向回调函数传入false
callBackResult?.Invoke(false);
return;
}
abDic[abName].Unload(false);
abDic.Remove(abName);
//卸载成功,向回调函数传入true
callBackResult?.Invoke(true);
}
}

//所有包的卸载
public void ClearAB()
{
//由于AB包都是异步加载,同时停止所有的异步加载协程
StopAllCoroutines();
AssetBundle.UnloadAllAssetBundles(false);
abDic.Clear();
//卸载主包,卸载依赖文件
mainAB = null;
manifest = null;
}
}