WP7 性能优化系列 (1)

来源:互联网 发布:linux开ftp 编辑:程序博客网 时间:2024/06/14 16:21

1.    Image

默认情况下所有的图片的解码过程都是在UI线程同步进行,所以如果用如下方式显示图片将会阻塞UI线程:

<Image Source=”{Binding ImageUrl}”/>

 以上方式UI线程将对图片解码,此过程中UI会一直阻塞直到图片解码结束。

 解决方式如下:

<Image>

<Image.Source>

<BitmapImage UriSource="{Binding ImgUrl}" CreateOptions="BackgroundCreation"/>

</Image.Source>

</Image>

这两种显示图片方式在模拟器上验证时,不会对应用产生有明显的效果差别,因为在模拟器中对手机处理器的速度没有模拟

注意:用第二种种方式显示图片时在Blend中会提示“Invalid xaml”

详细信息请参考文章: http://blogs.msdn.com/b/slmperf/archive/2011/06/13/off-thread-decoding-of-images-on-mango-how-it-impacts-you-application.aspx 

2.    ListBox(ItemsControl)

需要在一个集合中显示不同类型的数据时,例如新鲜事、日志、状态等,往往会采用自定集合控件,然后在控件里根据数据类型采用不同的数据模板(具体做法将在错误用法里谈到)。这样的做法最大的影响就是放弃ListBox的缓冲机制,当ListBox发现它缓存的模板不能满足数据的需要时就会放弃缓存,这样做的结果就是只有在列表项Loaded时才匆忙的读取数据、寻找模板、加载到集合容器中,会造成很糟的用户体验。

正确的做法是把需要显示的所有模板放到一个数据模板中,然后使用例如Converter的方式(Converter的系统资源很小)决定显示/隐藏相应的模板。 

下面将分别介绍两种做法:

首先准备必要数据:

数据类 A、B (即要显示的不同数据类型), 数据源

复制代码
 private ObservableCollection<object> dataSource = new ObservableCollection<object>();        public ObservableCollection<object> DataSource        {            get { return dataSource; }            set            {                dataSource = value;                if (this.PropertyChanged != null)                {                    this.PropertyChanged(this, new PropertyChangedEventArgs("DataSource"));                }            }        }        public MainPage()        {            InitializeComponent();            this.DataContext = this;            this.DataSource.Add(new A() { ID = 1, Name = "John", Department = "Product" });            this.DataSource.Add(new B() {  Title = "PM", Comment = "this is me" });            this.DataSource.Add(new A() { ID = 1, Name = "John", Department = "Product" });            this.DataSource.Add(new B() { Title = "Dev", Comment = "this is he" });            this.DataSource.Add(new B() { Title = "Designer", Comment = "this is cat" });            this.DataSource.Add(new A() { ID = 1, Name = "John", Department = "Product" });        }
复制代码

错误用法:

u  在资源中定义不同的样式          

复制代码
 <DataTemplate x:Key="Tp1">            <StackPanel Orientation="Horizontal"  HorizontalAlignment="Left">                <TextBlock Text="{Binding ID}" Width="50"></TextBlock>                <TextBlock Text="{Binding Name}" Margin="0 5" Width="100"></TextBlock>                <TextBlock Text="{Binding Department}"></TextBlock>            </StackPanel>        </DataTemplate>        <DataTemplate x:Key="Tp2">            <StackPanel Orientation="Horizontal" >                <TextBlock Text="{Binding Title}" Width="100"  Foreground="Orange"></TextBlock>                <TextBlock Text="{Binding Comment}" Foreground="Orange"></TextBlock>            </StackPanel>        </DataTemplate>
复制代码

u  自定义集合控件,并在控件中寻找不同的数据模板 

复制代码
 public class MyListBox : ItemsControl    {        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)        {            base.PrepareContainerForItemOverride(element, item);            var container = (element as ContentPresenter);            var tmp = (App.Current as App).Resources["Tp1"] as DataTemplate;            if (item is B)            {                tmp = (App.Current as App).Resources["Tp2"] as DataTemplate;            }            container.ContentTemplate = tmp;        }    }
复制代码

u  使用时没有区别 

复制代码
  <ctr:MyListBox ItemsSource="{Binding DataSource}">           <ctr:MyListBox.ItemsPanel>                     <ItemsPanelTemplate>                            <StackPanel Orientation="Vertical"></StackPanel>                      </ItemsPanelTemplate>            </ctr:MyListBox.ItemsPanel>   </ctr:MyListBox>
复制代码

以上就是普通的错误用法。 

下面展示正确的做法:

u  在资源中定义数据模板 

复制代码
  <DataTemplate x:Key="TP">            <Grid>                <StackPanel x:Name="AT" Orientation="Horizontal"  HorizontalAlignment="Left"                            Visibility="{Binding Converter={StaticResource DataTypeToVisibilityConverter}, ConverterParameter=AT}">                    <TextBlock Text="{Binding ID}" Width="50"></TextBlock>                    <TextBlock Text="{Binding Name}" Margin="0 5" Width="100"></TextBlock>                    <TextBlock Text="{Binding Department}"></TextBlock>                </StackPanel>                <StackPanel x:Name="BT" Orientation="Horizontal"                             Visibility="{Binding Converter={StaticResource DataTypeToVisibilityConverter}, ConverterParameter=BT}">                    <TextBlock Text="{Binding Title}" Width="100"  Foreground="Orange"></TextBlock>                    <TextBlock Text="{Binding Comment}" Foreground="Orange"></TextBlock>                </StackPanel>            </Grid></DataTemplate>
复制代码

u  做转换器Converter 

复制代码
  public class DataTypeToVisibilityConverter : IValueConverter    {        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)        {            if (null == parameter || value == null)            {                return Visibility.Collapsed;            }            if (value is A && "AT".Equals(parameter.ToString()))            {                return Visibility.Visible;            }            if (value is B && "BT".Equals(parameter.ToString()))            {                return Visibility.Visible;            }            return Visibility.Collapsed;        }        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)        {            throw new NotImplementedException();        }    }
复制代码

u  使用时无区别 

<ListBox Margin="0 20 0 0" ItemTemplate="{StaticResource TP}" ItemsSource="{Binding DataSource}"></ListBox>

u  运行效果一样,下图显示两中做法的共同效果

 

可以看出两种做法的运行结果完全一样,但是数据结构比较复杂时第二种做法就提现了缓存的优势。

原创粉丝点击