大量网络图片列表的异步加载和内存优化

来源:互联网 发布:win10禁止软件运行 编辑:程序博客网 时间:2024/04/28 08:07
<ListBox x:Name="lb">                <ListBox.ItemTemplate>                <DataTemplate>                    <Grid>                        <Grid.ColumnDefinitions>                            <ColumnDefinition Width="100"/>                            <ColumnDefinition Width="*"/>                        </Grid.ColumnDefinitions>                        <TextBlock Text="{Binding Name}"/>                        <Image Source="{Binding ImageSource}" Height="200"/>                    </Grid>                </DataTemplate>                </ListBox.ItemTemplate>        </ListBox>
  public class Data : INotifyPropertyChanged    {        //图片名        public string Name { get; set; }        //当前页面对象用于角发UI线程        public Page Page { get; set; }        private Uri imageUri;        public Uri ImageUri        {            get { return imageUri; }            set            {                if (value != imageUri)                {                    imageUri = value;                }            }        }        WeakReference bitmapImage;        public ImageSource ImageSource        {            get            {                if (bitmapImage != null)                {                    if (bitmapImage.IsAlive)                    {                        return (ImageSource)bitmapImage.Target;                    }                    else                    {                        Debug.WriteLine("图片占用的被回收了");                    }                }                if (imageUri != null)                {                    Task.Factory.StartNew(() =>                        {                            DownloadImage(imageUri);                        });                }                return null;            }        }        void DownloadImage(object state)        {            HttpWebRequest request = WebRequest.CreateHttp(state as Uri);            request.BeginGetResponse(DownLoadImageComplete, request);        }         void DownLoadImageComplete(IAsyncResult result)        {            HttpWebRequest request = result.AsyncState as HttpWebRequest;            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);            Stream stream = response.GetResponseStream();            int length = int.Parse(response.Headers["Content-Length"]);            Stream streamForUri = new MemoryStream(length);            byte[] buffer = new Byte[length];            int read = 0;            do            {                read = stream.Read(buffer, 0, length);                streamForUri.Write(buffer, 0, read);            }            while(read==length);            streamForUri.Seek(0, SeekOrigin.Begin);             Page.Dispatcher.BeginInvoke(() =>                {                    BitmapImage bm = new BitmapImage();                    bm.SetSource(streamForUri);                    if (bitmapImage == null)                    {                        bitmapImage = new WeakReference(bm);                    }                    else                    {                        bitmapImage.Target = bm;                    }                    OnPropertyChanged("ImageSource");                });        }        public event PropertyChangedEventHandler PropertyChanged;        private void OnPropertyChanged(string proName)        {            if (PropertyChanged != null)            {                PropertyChanged(this, new PropertyChangedEventArgs(proName));            }        }    }
 List<Data> list = new List<Data>();            for (int i = 0; i < 1000; i++)            {                list.Add(new Data                {                    Page = this,                    Name = i.ToString(),                    ImageUri = new Uri("http://static.cnbetacdn.com/newsimg/110510/0657270304679663.jpg", UriKind.RelativeOrAbsolute),                });            }            lb.ItemsSource = list;

这贴子内容来自<深入理解windows phone 8.1 UI控件编程>301

使用书上的代码对ListBox进行测试,发现改变ListBox的ScrollViewer和ItemPresenter的结构,会使用虚拟化功能失效.

默认情况下应该是这样的:

 <ListBox.Template>    <ControlTemplate TargetType="ListBox">         <ScrollViewer>              <ItemsPresenter/>          </ScrollViewer></span>     </ControlTemplate> </ListBox.Template>
改变ScrollViewer和ItemPresenter的结构,就是类似这样(只要是ScrollViewer和ItemPresenter之间加入了其它控件就破坏了虚拟化功能)
  <ListBox.Template>       <ControlTemplate TargetType="ListBox">              <ScrollViewer>                   <StackPanel Orientation="Vertical">                         <ItemsPresenter/>                         <Button Content="这样就完全破坏了虚拟化功能"/>                    </StackPanel>              </ScrollViewer></span>       </ControlTemplate>  </ListBox.Template>

在大多数情况下,最浪费时间的就是UI的创建.虚拟化功能可以保证只创建屏幕区域内的UI元素,如果数据源中包含的元素数据量过多时,虚拟化功能可以节约程序的内存.如果像上面一样坏虚拟化功能,在使用大数据源初始化ListBox后,会一次性创建所有列表基, 手机的内存可能会吃不销.

上面那个例子是异步加载图片,然后用ListBox显示,这个例子有两个性能问题.

1 Data对象中图片占用的内存

把ImageSource属性设置成WeakRefrence是为了,让图片对象尽可能快的被GC回收来释放内存.


3.异步加载.




0 0
原创粉丝点击