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

<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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值