Добавил кэширование поскейленных картинок, чтобы расходовать меньше батарейки и сетевого трафика
This commit is contained in:
@@ -64,6 +64,8 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Assets\Scripts\Cache.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\CacheDescription.cs" />
|
||||||
<Compile Include="Assets\Scripts\Clock.cs" />
|
<Compile Include="Assets\Scripts\Clock.cs" />
|
||||||
<Compile Include="Assets\Scripts\CoroutineRunner.cs" />
|
<Compile Include="Assets\Scripts\CoroutineRunner.cs" />
|
||||||
<Compile Include="Assets\Scripts\FpsController.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;
|
InputField url;
|
||||||
|
|
||||||
private int currentImage;
|
private int currentImage;
|
||||||
|
private Cache cache;
|
||||||
|
|
||||||
private Image CurrentImage
|
private Image CurrentImage
|
||||||
{
|
{
|
||||||
@@ -33,6 +34,7 @@ public class PhotoFrame : MonoBehaviour
|
|||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
|
cache = new Cache(Application.persistentDataPath);
|
||||||
Screen.sleepTimeout = SleepTimeout.NeverSleep;
|
Screen.sleepTimeout = SleepTimeout.NeverSleep;
|
||||||
currentImage = 0;
|
currentImage = 0;
|
||||||
ActivateUI(true);
|
ActivateUI(true);
|
||||||
@@ -89,6 +91,15 @@ public class PhotoFrame : MonoBehaviour
|
|||||||
int imageIndex = Random.Range(0, loader.images.Count);
|
int imageIndex = Random.Range(0, loader.images.Count);
|
||||||
string imageUrl = loader.images[imageIndex];
|
string imageUrl = loader.images[imageIndex];
|
||||||
|
|
||||||
|
var bytes = cache.Get(imageUrl);
|
||||||
|
if (bytes != null)
|
||||||
|
{
|
||||||
|
var tex = new Texture2D(2, 2);
|
||||||
|
tex.LoadImage(bytes);
|
||||||
|
SetImageTexture(NextImage, tex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
var request = UnityWebRequest.Get(imageUrl);
|
var request = UnityWebRequest.Get(imageUrl);
|
||||||
request.downloadHandler = new DownloadHandlerTexture(true);
|
request.downloadHandler = new DownloadHandlerTexture(true);
|
||||||
yield return request.SendWebRequest();
|
yield return request.SendWebRequest();
|
||||||
@@ -111,6 +122,8 @@ public class PhotoFrame : MonoBehaviour
|
|||||||
SetImageTexture(NextImage, tex);
|
SetImageTexture(NextImage, tex);
|
||||||
dh.Dispose();
|
dh.Dispose();
|
||||||
request.Dispose();
|
request.Dispose();
|
||||||
|
cache.Add(imageUrl, tex.EncodeToJPG());
|
||||||
|
}
|
||||||
|
|
||||||
float currentStart = CurrentImage.color.a;
|
float currentStart = CurrentImage.color.a;
|
||||||
float currentFinish = transparent.a;
|
float currentFinish = transparent.a;
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ PlayerSettings:
|
|||||||
16:10: 1
|
16:10: 1
|
||||||
16:9: 1
|
16:9: 1
|
||||||
Others: 1
|
Others: 1
|
||||||
bundleVersion: 0.1
|
bundleVersion: 0.2
|
||||||
preloadedAssets: []
|
preloadedAssets: []
|
||||||
metroInputSource: 0
|
metroInputSource: 0
|
||||||
wsaTransparentSwapchain: 0
|
wsaTransparentSwapchain: 0
|
||||||
|
|||||||
Reference in New Issue
Block a user