Comment faire pour récupérer le nombre total de bytes des fichiers lorsque le chargement n'a pas commencé ? Masapi gère la chose très simplement : tous les fichiers ont le même poids (bytesTotal) jusqu'à ce que cette valeur soit connue. Dès que la propriété bytesTotal d'un fichier est récupérée, masapi va automatiquement l'utiliser (et laisser tomber le poids par défaut).

Coté code, la propriété qui est utilisée se nomme virtualBytesTotal de l'interface ILoadableFile. Par défaut, la classe LoadableFileFactory mettra une valeur de 200ko à cette valeur. La plupart du temps, celle-ci est suffisante car les fichiers sont assez légers.

Toutefois, cela peut poser problème lorsque les fichiers à charger sont gros (dépassent les 200Ko). Si un loader séquentiel (fichiers chargés 1 par 1) est utilisé, tout d'un coup la barre de progression va reculer ! Dans le cas contraire, avec des fichiers très légers, la barre de progression avancera très lentement et arrivera d'un coup à la fin.

Voila un exemple d'une très mauvaise utilisation de la propriété virtualBytesTotal. La barre du haut, tous les fichiers font 10Mo par défaut et pour celle du bas, 2Ko. L'image chargée fait 2.5Mo.

MasapiComplexDependency

J'ai créé ci-dessous un autre exemple où 1 fichier de 2.5Mo est chargé et ensuite 8 fichiers de 1Ko. La barre du haut montre le comportement avec les valeurs par défaut et celle du bas avec des valeurs personnalisées :

MasapiComplexDependency

Dans le deuxième cas, l'avancée des pourcentages reflète mieux la réalité qu'avec les valeurs par défaut, quoique celles-ci fonctionnent très bien.

Du coté du code, cela reste assez simple. Voici le code de base utilisé :

var cpLoader:CompositeMassLoader = new CompositeMassLoader();
cpLoader.massLoader.parallelFiles = 1;
 
var rootPath:String = "./";
var file1:ILoadableFile = cpLoader.addFile(rootPath+"picture.jpg"); //2.5Mo
var file2:ILoadableFile = cpLoader.addFile(rootPath+"file1.txt", LoadableFileType.TEXT); //1Ko
var file3:ILoadableFile = cpLoader.addFile(rootPath+"file2.txt", LoadableFileType.TEXT);
var file4:ILoadableFile = cpLoader.addFile(rootPath+"file3.txt", LoadableFileType.TEXT);
var file5:ILoadableFile = cpLoader.addFile(rootPath+"file4.txt", LoadableFileType.TEXT);
var file6:ILoadableFile = cpLoader.addFile(rootPath+"file5.txt", LoadableFileType.TEXT);
var file7:ILoadableFile = cpLoader.addFile(rootPath+"file6.txt", LoadableFileType.TEXT);
var file8:ILoadableFile = cpLoader.addFile(rootPath+"file7.txt", LoadableFileType.TEXT);
var file9:ILoadableFile = cpLoader.addFile(rootPath+"file8.txt", LoadableFileType.TEXT);
 
cpLoader.start();

Pourquoi avec ce morceau de code, le comportement n'est pas le même que dans le premier exemple avec la barre qui recule ? Tout simplement car Masapi reçoit très rapidement la bonne valeur bytesTotal du fichier et n'utilise plus la propriété virtualBytesTotal. Toutefois, la barre de progression continue d'avancer lentement car Masapi pense qu'il y a encore 8 fichiers de 200Ko à charger.

Pour adapter cela, il y a la solution simple mais fastidieuse suivante : pour chacun des fichiers créés, adapter manuellement la propriété virtualBytesTotal.

var file:ILoadableFile = cpLoader.addFile(rootPath+"file8.txt", LoadableFileType.TEXT);
file.virtualBytesTotal = 2000; //2Ko

L'autre méthode consiste à dire à la classe LoadableFileFactory de mettre directement la valeur désirée, et d'adapter cette valeur pour le fichier qui est beaucoup plus lourd.

var cpLoader:CompositeMassLoader = new CompositeMassLoader();
cpLoader.loadableFileFactory.defaultVirtualBytesTotal = 2000;
cpLoader.massLoader.parallelFiles = 1;
 
var rootPath:String = "./";
var file1:ILoadableFile = cpLoader.addFile(rootPath+"picture.jpg"); //2.5Mo
file1.virtualBytesTotal = 2.5 * 1024 * 1000; //2.5Mo par défaut
 
var file2:ILoadableFile = cpLoader.addFile(rootPath+"file1.txt", LoadableFileType.TEXT); //2Ko par défaut
var file3:ILoadableFile = cpLoader.addFile(rootPath+"file2.txt", LoadableFileType.TEXT);
var file4:ILoadableFile = cpLoader.addFile(rootPath+"file3.txt", LoadableFileType.TEXT);
var file5:ILoadableFile = cpLoader.addFile(rootPath+"file4.txt", LoadableFileType.TEXT);
var file6:ILoadableFile = cpLoader.addFile(rootPath+"file5.txt", LoadableFileType.TEXT);
var file7:ILoadableFile = cpLoader.addFile(rootPath+"file6.txt", LoadableFileType.TEXT);
var file8:ILoadableFile = cpLoader.addFile(rootPath+"file7.txt", LoadableFileType.TEXT);
var file9:ILoadableFile = cpLoader.addFile(rootPath+"file8.txt", LoadableFileType.TEXT);
 
cpLoader.start();

Et l'avancement du pourcentage sera beaucoup mieux géré ! Il faut juste bien retenir que la propriété virtualBytesTotal est utilisée seulement si la valeur bytesTotal d'un fichier chargé n'est pas connue.

La bonne pratique pour gérer ce genre de chose est de spécifier une taille légèrement supérieure à la taille réélle du fichier. Par exemple, pour une liste de fichiers dont le poids est compris entre 10 et 30Ko, la valeur de virtualBytesTotal devrait être à 35Ko. Il faut éviter d'avoir une valeur inférieur à la taille d'un fichier sous peine de voir sa barre de progression reculer. Dans le doute, une valeur élevée est de mise.

Enfin pour ceux qui utiliser l'inter-dépendance des fichiers, il n'y a aucune ligne de code à toucher pour ajuster cela : il suffit de rajouter l'attribut virtualBytesTotal dans le xml de configuration :

<?xml version="1.0" encoding="utf-8" ?>
<application>
        <files>
                <file name="astorm"     url="/blog/public/Sources/Masapi/Dependency/astorm.swf"     type="swf"     virtualBytesTotal="200000" />
                <file name="font"       url="/blog/public/Sources/Masapi/Dependency/font.swf"       type="swf"     virtualBytesTotal="500000" />
                <file name="background" url="/blog/public/Sources/Masapi/Dependency/storm.jpg"      type="swf"     virtualBytesTotal="1000000" />
		<file name="text"	url="/blog/public/Sources/Masapi/Dependency/text.txt"	    type="text"    virtualBytesTotal="30000" />
        </files>
        <dependencies>
		<dependency name="astorm">
			<file name="font" />
			<file name="background" />
			<file name="text" />
		</dependency>
	</dependencies>
</application>