你的位置:首页 > 操作系统

[操作系统]UWP开发中两种网络图片缓存方法


  通常情况下,我们的程序需要从服务器读取图片,但如果需要不止一次读取某一张图片的话,就需要做本地缓存了,这样既为用户省一点流量,又能显得你的APP很快。

  假如你已经知道了某一张图片的地址,那么第一件事就是要把这张图片下载下来;当然如果是一次性读取的话,可以直接把图片地址给Image控件或者给Bitmapimage对象(实际上这二者是没有去别的),但这无法存到本地,只作为显示用;但是我们要做的是保存到本地,这样肯定是不行的。现在我们就要用到HTTP的东西了,请看下面的代码:

      async static public Task<IInputStream> GetStreamAsync(string url)    {      httpClient = new HttpClient();      var response = await httpClient.GetInputStreamAsync(new Uri(url));      return response;    } async static public Task<IBuffer> GetBufferAsync(string url)    {      httpClient = new HttpClient();            var ResultStr = await httpClient.GetBufferAsync(new Uri(url));      return ResultStr;    }

这两个静态方法分别获取url地址的buffer数据和输入流。有了buffer或者stream之后就可以进行下一步-保存。

  当我们下载完成后,首先要做的很有可能是先显示出来,然后再保存,所以先把数据写入到图片对象中:

这里有两种方法:

1.WriteableBitmap

 protected async Task<WriteableBitmap> GetWriteableBitmapAsync(string url)    {      try      {        IBuffer buffer = await GetBufferAsync(url);        if (buffer != null)        {          BitmapImage bi = new BitmapImage();          WriteableBitmap wb = null; Stream stream2Write;          using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())          {            stream2Write = stream.AsStreamForWrite();            await stream2Write.WriteAsync(buffer.ToArray(), 0, (int)buffer.Length);            await stream2Write.FlushAsync();            stream.Seek(0);            await bi.SetSourceAsync(stream);            wb = new WriteableBitmap(bi.PixelWidth, bi.PixelHeight);            stream.Seek(0);            await wb.SetSourceAsync(stream);            return wb;          }        }        else        {          return null;        }      }      catch      {        return null;      }    }

2.SoftwareBitmap

public async Task<SoftwareBitmap> GetSoftwareBitmapAsync(string url)    {      try      {        IInputStream inputStream = await GetSteramAsync(url);        IRandomAccessStream memStream = new InMemoryRandomAccessStream();        await RandomAccessStream.CopyAsync(inputStream, memStream);        BitmapDecoder decoder = await BitmapDecoder.CreateAsync(memStream);        SoftwareBitmap sb = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);        return sb;      }      catch       {        return null;      }    }

这两种都可以作为展示图像的数据源,其中WriteableBitmap可以直接给Image.Source , SoftwareBitmap这需要转为SoftwareBitmap:

          SoftwareBitmapSource sbs = new SoftwareBitmapSource();        sbs.SetBitmapAsync(sb);

接下来就是保存了:WriteableBitmap:

 public async Task SaveImageAsync(WriteableBitmap image, string filename)    {      try      {        if (image == null)        {          return;        }        Guid BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;        if (filename.EndsWith("jpg"))          BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;        else if (filename.EndsWith("png"))          BitmapEncoderGuid = BitmapEncoder.PngEncoderId;        else if (filename.EndsWith("bmp"))          BitmapEncoderGuid = BitmapEncoder.BmpEncoderId;        else if (filename.EndsWith("tiff"))          BitmapEncoderGuid = BitmapEncoder.TiffEncoderId;        else if (filename.EndsWith("gif"))          BitmapEncoderGuid = BitmapEncoder.GifEncoderId;        var folder = await _local_folder.CreateFolderAsync("images_cache", CreationCollisionOption.OpenIfExists);        var file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);        using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))        {          BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);          Stream pixelStream = image.PixelBuffer.AsStream();          byte[] pixels = new byte[pixelStream.Length];          await pixelStream.ReadAsync(pixels, 0, pixels.Length);          encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,               (uint)image.PixelWidth,               (uint)image.PixelHeight,               96.0,               96.0,               pixels);          await encoder.FlushAsync();        }      }      catch      {      }    }

public async Task WriteToFileAsync(StorageFolder folder,SoftwareBitmap sb,string fileName)    {            if (sb != null)      {        // save image file to cache        StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);        using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))        {          BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);          encoder.SetSoftwareBitmap(sb);          await encoder.FlushAsync();        }      }    }

怎么样,是不是很简单?