Добавил кэширование поскейленных картинок, чтобы расходовать меньше батарейки и сетевого трафика
This commit is contained in:
@@ -64,6 +64,8 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Assets\Scripts\Cache.cs" />
|
||||
<Compile Include="Assets\Scripts\CacheDescription.cs" />
|
||||
<Compile Include="Assets\Scripts\Clock.cs" />
|
||||
<Compile Include="Assets\Scripts\CoroutineRunner.cs" />
|
||||
<Compile Include="Assets\Scripts\FpsController.cs" />
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
public class Cache
|
||||
{
|
||||
const int MAX_ELEMENTS = 1000;
|
||||
const string CACHE_DESCRIPTION_FILE = "files.dat";
|
||||
const string CACHE_DATA_DIR = "data";
|
||||
|
||||
private string rootPath;
|
||||
private CacheDescription description;
|
||||
|
||||
public Cache(string path)
|
||||
{
|
||||
rootPath = path;
|
||||
if (!Directory.Exists(GetDataPath()))
|
||||
{
|
||||
Directory.CreateDirectory(GetDataPath());
|
||||
}
|
||||
LoadDescription();
|
||||
CleanupDataDirectory();
|
||||
}
|
||||
|
||||
private string GetDataPath()
|
||||
{
|
||||
return rootPath + "/" + CACHE_DATA_DIR;
|
||||
}
|
||||
|
||||
private void CleanupDataDirectory()
|
||||
{
|
||||
var directory = GetDataPath();
|
||||
var di = new DirectoryInfo(directory);
|
||||
var files = di.GetFiles();
|
||||
foreach (var f in files)
|
||||
{
|
||||
if (!description.path.ContainsKey(f.Name))
|
||||
{
|
||||
File.Delete(directory + "/" + f.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string RandomName()
|
||||
{
|
||||
string result = "";
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
int t = UnityEngine.Random.Range(0, 36);
|
||||
if (t < 10) result += (char)(t + '0');
|
||||
else result += (char)(t - 10 + 'a');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void LoadDescription()
|
||||
{
|
||||
var path = rootPath + "/" + CACHE_DESCRIPTION_FILE;
|
||||
try
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
Stream openFileStream = File.OpenRead(path);
|
||||
BinaryFormatter deserializer = new BinaryFormatter();
|
||||
description = (CacheDescription)deserializer.Deserialize(openFileStream);
|
||||
openFileStream.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
description = new CacheDescription();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
description = new CacheDescription();
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string path, byte[] data)
|
||||
{
|
||||
if (!description.path.ContainsKey(path))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var fileName = RandomName();
|
||||
if (!File.Exists(GetDataPath() + "/" + fileName))
|
||||
{
|
||||
description.path[path] = fileName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
var filePath = GetDataPath() + "/" + description.path[path];
|
||||
File.WriteAllBytes(filePath, data);
|
||||
description.lastUse[path] = DateTime.Now;
|
||||
PurgeCache();
|
||||
SaveDescription();
|
||||
}
|
||||
|
||||
private void SaveDescription()
|
||||
{
|
||||
var path = rootPath + "/" + CACHE_DESCRIPTION_FILE;
|
||||
try
|
||||
{
|
||||
BinaryFormatter serializer = new BinaryFormatter();
|
||||
Stream openFileStream = File.OpenWrite(path);
|
||||
serializer.Serialize(openFileStream, description);
|
||||
openFileStream.Close();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
description = new CacheDescription();
|
||||
}
|
||||
}
|
||||
|
||||
private void PurgeCache()
|
||||
{
|
||||
// throw away excess elements
|
||||
// for now will use slow implementation
|
||||
while (description.path.Count >= MAX_ELEMENTS)
|
||||
{
|
||||
DateTime min = DateTime.MaxValue;
|
||||
string mpath = null;
|
||||
foreach (var kv in description.lastUse)
|
||||
{
|
||||
if (kv.Value < min)
|
||||
{
|
||||
min = kv.Value;
|
||||
mpath = kv.Key;
|
||||
}
|
||||
}
|
||||
// not found?
|
||||
if (mpath == null) break;
|
||||
try
|
||||
{
|
||||
File.Delete(GetDataPath() + "/" + description.path[mpath]);
|
||||
}
|
||||
catch (IOException) { }
|
||||
description.path.Remove(mpath);
|
||||
description.lastUse.Remove(mpath);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Get(string path)
|
||||
{
|
||||
if (!description.path.ContainsKey(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
description.lastUse[path] = DateTime.Now;
|
||||
return File.ReadAllBytes(GetDataPath() + "/" + description.path[path]);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab7ecde33614955458f63144323618b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[Serializable]
|
||||
public class CacheDescription
|
||||
{
|
||||
public Dictionary<string, string> path;
|
||||
public Dictionary<string, DateTime> lastUse;
|
||||
|
||||
public CacheDescription()
|
||||
{
|
||||
path = new Dictionary<string, string>();
|
||||
lastUse = new Dictionary<string, DateTime>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0520a1857b831224aac90f9eac2c5772
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -20,6 +20,7 @@ public class PhotoFrame : MonoBehaviour
|
||||
InputField url;
|
||||
|
||||
private int currentImage;
|
||||
private Cache cache;
|
||||
|
||||
private Image CurrentImage
|
||||
{
|
||||
@@ -33,6 +34,7 @@ public class PhotoFrame : MonoBehaviour
|
||||
|
||||
public void Start()
|
||||
{
|
||||
cache = new Cache(Application.persistentDataPath);
|
||||
Screen.sleepTimeout = SleepTimeout.NeverSleep;
|
||||
currentImage = 0;
|
||||
ActivateUI(true);
|
||||
@@ -89,29 +91,40 @@ public class PhotoFrame : MonoBehaviour
|
||||
int imageIndex = Random.Range(0, loader.images.Count);
|
||||
string imageUrl = loader.images[imageIndex];
|
||||
|
||||
var request = UnityWebRequest.Get(imageUrl);
|
||||
request.downloadHandler = new DownloadHandlerTexture(true);
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.isNetworkError || request.isHttpError)
|
||||
var bytes = cache.Get(imageUrl);
|
||||
if (bytes != null)
|
||||
{
|
||||
yield return new WaitForSeconds(1f);
|
||||
continue;
|
||||
var tex = new Texture2D(2, 2);
|
||||
tex.LoadImage(bytes);
|
||||
SetImageTexture(NextImage, tex);
|
||||
}
|
||||
|
||||
var downloadTime = Time.realtimeSinceStartup - startTime;
|
||||
if (PHOTO_INTERVAL > downloadTime)
|
||||
else
|
||||
{
|
||||
yield return new WaitForSeconds(PHOTO_INTERVAL - downloadTime);
|
||||
var request = UnityWebRequest.Get(imageUrl);
|
||||
request.downloadHandler = new DownloadHandlerTexture(true);
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.isNetworkError || request.isHttpError)
|
||||
{
|
||||
yield return new WaitForSeconds(1f);
|
||||
continue;
|
||||
}
|
||||
|
||||
var downloadTime = Time.realtimeSinceStartup - startTime;
|
||||
if (PHOTO_INTERVAL > downloadTime)
|
||||
{
|
||||
yield return new WaitForSeconds(PHOTO_INTERVAL - downloadTime);
|
||||
}
|
||||
|
||||
var dh = request.downloadHandler as DownloadHandlerTexture;
|
||||
var tex = dh.texture;
|
||||
|
||||
SetImageTexture(NextImage, tex);
|
||||
dh.Dispose();
|
||||
request.Dispose();
|
||||
cache.Add(imageUrl, tex.EncodeToJPG());
|
||||
}
|
||||
|
||||
var dh = request.downloadHandler as DownloadHandlerTexture;
|
||||
var tex = dh.texture;
|
||||
|
||||
SetImageTexture(NextImage, tex);
|
||||
dh.Dispose();
|
||||
request.Dispose();
|
||||
|
||||
float currentStart = CurrentImage.color.a;
|
||||
float currentFinish = transparent.a;
|
||||
float nextStart = NextImage.color.a;
|
||||
|
||||
@@ -118,7 +118,7 @@ PlayerSettings:
|
||||
16:10: 1
|
||||
16:9: 1
|
||||
Others: 1
|
||||
bundleVersion: 0.1
|
||||
bundleVersion: 0.2
|
||||
preloadedAssets: []
|
||||
metroInputSource: 0
|
||||
wsaTransparentSwapchain: 0
|
||||
|
||||
Reference in New Issue
Block a user