淘寶UWP--自定義圖片緩存

1、應用場景

在淘寶應用首頁,會有不少張圖片,而這些首頁圖片不會常常改變,因此就須要緩存下來。這樣就沒必要每次都從網絡獲取。數組

2、比較對象

1.系統緩存

對於系統緩存,咱們不須要作什麼處理。只須要把網絡圖片的URL賦值給Image控件就好了。這樣系統就會在每次須要用到圖片的時候,有限查找緩存裏有沒有以前下載好的。緩存

2.自建緩存區域

自建緩存不給Image控件賦URL,而是把圖片DownLoad下來,生成一個bitmap,而後把bitmap賦值給Image。同時將這個bitmap存儲下來。當下次要用到這幅圖的時候,就直接從存儲的位置找到這幅圖。網絡

3、自建緩存方法

下邊這段代碼將uri[]數組中的圖片下載下來,而後經過WriteToFile()函數將圖片保存到本地,同時,記下存儲的文件名。dom

SoftwareBitmap sb = await DownloadImage(uri[i]);
if (sb != null)
{
  //sb = await ReadFromFile(fileName[i]);
  SoftwareBitmapSource source = new SoftwareBitmapSource();
  await source.SetBitmapAsync(sb);
  this.insideImage.Source = source;
  sb = await DownloadImage(uri[i]);
  fileName[i] = await WriteToFile(sb);
}


當你須要使用圖片的時候,使用下列代碼,經過ReadFromFile()函數將圖片讀取出來就好了。異步

for (int i = 0; i < 50; i++)
{
  
//SoftwareBitmap sb = await DownloadImage(uri[i]);   SoftwareBitmap sb = await ReadFromFile(fileName[i]);   SoftwareBitmapSource source = new SoftwareBitmapSource();
  await source.SetBitmapAsync(sb);   this.insideImage.Source = source;
  //source.Dispose(); }

 

4、效率對比

下邊我經過對比兩種緩存機制發現各有用武之地。async

1.對於幾百K到幾兆的大圖片,系統緩存有速度優點。ide

2.對於幾K到幾十K的小圖片,自建緩存區有速度優點。函數

測試背景1:三張大圖片,循環33次(共99次) 測試

圖片大小:338k 618k 1810k this

 

PC測試

         

系統緩存(CPU週期)

3066584

3058505

3079367

3078989

3076976

自建緩存(CPU週期)

53669280

51842991

52839051

52078772

52305373

 

Phone測試

       

系統緩存(CPU週期)

31852799

32008575

32200748

31970601

31839003

自建緩存(CPU週期)

741909215

750950455

765863510

760865505

781048686

 

結論一:對於幾百K到幾兆的大圖片,系統緩存有速度優點。

 

測試背景2:三張小圖片,循環33次(共99次)

圖片大小:3k 6k 60k

PC測試

系統緩存(CPU週期)

3057284

3057637

3080880

3063350

3059105

自建緩存(CPU週期)

1316247

1318369

1364584

1333684

1362956

 

Phone測試

系統緩存(CPU週期)

32085084

31751734

31744715

31852230

32064768

自建緩存(CPU週期)

27114317

26041012

26821794

27365796

30211258

 

結論二:對於幾K到幾十K的小圖片,自建緩存區有速度優點。

 手機淘寶項目測試數據:

測試背景:50張小圖片,循環一次(共50次)

系統緩存

CPU週期

23689650

21589548

25409150

25186302

23121251

 

RAM

51

52

50

52

52

             
             

自建緩存

CPU週期

3186761

2892837

2963193

2942235

2741501

 

RAM

61

63

61

60

59

 PS:RAM佔用是峯值,穩定後兩種方式RAM佔用相同。

5、測試方法

經過給一個Image控件賦值,來看到效果。

一、系統緩存

系統緩存測試不能經過直接改變url的方式,由於系統緩存是異步的,他不會等一個圖片加載好再加載另外一個圖,而是直接忽略了以前的改變。

private async void test1()
{
  stopwatch.Reset();
  stopwatch.Start();
  BitmapImage bi = new BitmapImage();
  bi.UriSource = new Uri(uri[0]);
  this.insideImage.Source = bi;
 } 

private void insideImage_ImageOpened(object sender, RoutedEventArgs e)
{
  times++;
  if (times == 50)
  {
    stopwatch.Stop();
    textBox.Text = "任務"+testnum.ToString()+"用時:" + stopwatch.ElapsedTicks + ".";
    return;
  }

  BitmapImage bi = new BitmapImage();
  bi.UriSource = new Uri(uri[times]);
  this.insideImage.Source = bi;
 } 

 二、自建緩存

private async void test2()
{
  stopwatch.Reset();
  stopwatch.Start();
  for (int i = 0; i < 50; i++)
  {
    //SoftwareBitmap sb = await DownloadImage(uri[i]);
    SoftwareBitmap sb = await ReadFromFile(fileName[i]);
    SoftwareBitmapSource source = new SoftwareBitmapSource();
    await source.SetBitmapAsync(sb);
    if (i % 3 == 0)
    {
      this.insideImage.Source = source;
    }
    else if (i % 3 == 1)     {       this.insideImage1.Source = source;     }
    else if (i % 3 == 2)     {       this.insideImage2.Source = source;     }     //source.Dispose();
  }   stopwatch.Stop();   textBox.Text = "任務" + testnum.ToString() + "用時:" + stopwatch.ElapsedTicks + "."; }

 

附:關鍵代碼代碼

ReadFromFile()函數經過文件名讀取圖片 ,特別注意這句話

SoftwareBitmapsoftwareBitmap = awaitdecoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);

 必定要加上編碼方式,否則會報錯。

public async Task<SoftwareBitmap> ReadFromFile(string filename)
{
  StorageFile file = await _localFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists);
  //var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri( filename));
  using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
  {
    // Create the decoder from the stream
    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
    // Get the SoftwareBitmap representation of the file
    SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
    return softwareBitmap;
  }
}

 WriteToFile()函數將bitmap寫入存儲區

public async Task<string> WriteToFile(SoftwareBitmap softwareBitmap)
{
  string fileName = Path.GetRandomFileName();

  if (softwareBitmap != null)
  {
    // save image file to cache
    StorageFile file = await _localFolder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
    using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
    {
      BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
      encoder.SetSoftwareBitmap(softwareBitmap);
      await encoder.FlushAsync();
  }
}

  return fileName;
 } 

DownloadImage()函數經過url下載圖片,返回bitmap

private async Task<SoftwareBitmap> DownloadImage(string url)
{
  try
  {
    HttpClient hc = new HttpClient();
    HttpResponseMessage resp = await hc.GetAsync(new Uri(url));
    resp.EnsureSuccessStatusCode();
    IInputStream inputStream = await resp.Content.ReadAsInputStreamAsync();
    IRandomAccessStream memStream = new InMemoryRandomAccessStream();
    await RandomAccessStream.CopyAsync(inputStream, memStream);
    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(memStream);
    SoftwareBitmap softBmp = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
    return softBmp;
  }
  catch (Exception ex)
  {
    return null;
  }
}
相關文章
相關標籤/搜索