Добавил кэширование поскейленных картинок, чтобы расходовать меньше батарейки и сетевого трафика

This commit is contained in:
ftc
2021-05-27 23:59:12 +03:00
parent 98da719fcc
commit ca893f8687
7 changed files with 231 additions and 19 deletions
+160
View File
@@ -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;
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ab7ecde33614955458f63144323618b4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+15
View File
@@ -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>();
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0520a1857b831224aac90f9eac2c5772
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+31 -18
View File
@@ -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;