zoukankan      html  css  js  c++  java
  • Windows Phone零距离开发(Composite Thread组合线程)

    简洁流畅,快速响应是Windows Phone的特点也是他的买点,我们在开发App时候,也要在手机有限的硬件性能上最大限度做到UI快速响应,微软在优化手机快速响应这块做了很多底层优化工作,其中有一个就是我们要讨论的Composite Thread。

    Composite Thread这个中文叫组合线程也有翻译叫构图线程。很多人对Composite Thread都并不了解,也不知道这是干什么的,因为毕竟有关Composite Thread的有关资料确实很少,而且Composite Thread最早不是在WPF/Silverlight上实现的,而是首先在Silverlight For Windows Phone 7上实现的,等到Silverlight5才引进Composite Thread。

    说了那么多,那Composite Thread到底是可以用来干嘛用的,一言以蔽之就是,可以把动画剥离开UI线程到组合线程上执行

    在WP7开发中,我们如果用让用户等待一个耗时操作的完成,会用一个ProgressBar控件来提示让用户等待流程的完成。但ProgressBar有一个很不好的地方就是他是在UI线程上执行的,如果这个时候UI线程大量计算操作时候,ProgressBar就会卡成白痴(注:WP8的ProgressBar没有这个问题)。这个时候,一个叫做PerformanceProgressBar控件就闪亮登场出来救场了,PerformanceProgressBar很对得起它的Performance的Title,因为他可以做到不卡UI线程。

    可能大家很好奇,因为我们知道一般更改UI操作只能是在UI线程上进行,而动画也是在更改UI,但PerformanceProgressBar却可以在非UI线程上执行动画。PerformanceProgressBar是Silverlight For WP Toolkit下一个开源控件,我们可以直接通过源码来看到他的具体实现。

    通过源码我们可以看到PerformanceProgressBar仅仅只是在ProgressBar的基础上重新定制了他的Style

    <PerformanceProgressBar 
                    x:Name="customIndeterminateProgressBar"
                    IsIndeterminate="true"
                    Style="{StaticResource CustomIndeterminateProgressBar}"
                />
    <Style x:Key="CustomIndeterminateProgressBar" TargetType="ProgressBar">
                <Setter Property="Foreground" Value="{StaticResource PhoneAccentBrush}"/>
                <Setter Property="Background" Value="{StaticResource PhoneAccentBrush}"/>
                <Setter Property="Maximum" Value="100"/>
                <Setter Property="IsHitTestVisible" Value="False"/>
                <Setter Property="Padding" Value="{StaticResource PhoneHorizontalMargin}"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ProgressBar">
                            <unsupported:RelativeAnimatingContentControl HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
                                <unsupported:RelativeAnimatingContentControl.Resources>
                                    <ExponentialEase EasingMode="EaseOut" Exponent="1" x:Key="ProgressBarEaseOut"/>
                                    <ExponentialEase EasingMode="EaseOut" Exponent="1" x:Key="ProgressBarEaseIn"/>
                                </unsupported:RelativeAnimatingContentControl.Resources>
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Determinate"/>
                                        <VisualState x:Name="Indeterminate">
                                            <Storyboard RepeatBehavior="Forever" Duration="00:00:04.4">
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="IndeterminateRoot">
                                                    <DiscreteObjectKeyFrame KeyTime="0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <Visibility>Visible</Visibility>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DeterminateRoot">
                                                    <DiscreteObjectKeyFrame KeyTime="0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <Visibility>Collapsed</Visibility>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.0" Storyboard.TargetProperty="X" Storyboard.TargetName="R1TT">
                                                    <LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
                                                    <EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
                                                    <LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
                                                    <EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.2" Storyboard.TargetProperty="X" Storyboard.TargetName="R2TT">
                                                    <LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
                                                    <EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
                                                    <LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
                                                    <EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.4" Storyboard.TargetProperty="X" Storyboard.TargetName="R3TT">
                                                    <LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
                                                    <EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
                                                    <LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
                                                    <EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.6" Storyboard.TargetProperty="X" Storyboard.TargetName="R4TT">
                                                    <LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
                                                    <EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
                                                    <LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
                                                    <EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.8" Storyboard.TargetProperty="X" Storyboard.TargetName="R5TT">
                                                    <LinearDoubleKeyFrame KeyTime="00:00:00.0" Value="0.1"/>
                                                    <EasingDoubleKeyFrame KeyTime="00:00:00.5" Value="33.1" EasingFunction="{StaticResource ProgressBarEaseOut}"/>
                                                    <LinearDoubleKeyFrame KeyTime="00:00:02.0" Value="66.1"/>
                                                    <EasingDoubleKeyFrame KeyTime="00:00:02.5" Value="100.1" EasingFunction="{StaticResource ProgressBarEaseIn}"/>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R1">
                                                    <DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
                                                    <DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R2">
                                                    <DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
                                                    <DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R3">
                                                    <DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
                                                    <DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.6" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R4">
                                                    <DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
                                                    <DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
                                                </DoubleAnimationUsingKeyFrames>
                                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00.8" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="R5">
                                                    <DiscreteDoubleKeyFrame KeyTime="0" Value="1"/>
                                                    <DiscreteDoubleKeyFrame KeyTime="00:00:02.5" Value="0"/>
                                                </DoubleAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>
                                <Grid>
                                    <Grid x:Name="DeterminateRoot" Margin="{TemplateBinding Padding}" Visibility="Visible">
                                        <Rectangle x:Name="ProgressBarTrack" Fill="{TemplateBinding Background}" Height="4" Opacity="0.1"/>
                                        <Rectangle x:Name="ProgressBarIndicator" Fill="{TemplateBinding Foreground}" HorizontalAlignment="Left" Height="4"/>
                                    </Grid>
                                    <Border x:Name="IndeterminateRoot" Margin="{TemplateBinding Padding}" Visibility="Collapsed">
                                        <Grid HorizontalAlignment="Left">
                                            <Rectangle Fill="{TemplateBinding Foreground}" Height="4" IsHitTestVisible="False" Width="4" x:Name="R1" Opacity="0" CacheMode="BitmapCache">
                                                <Rectangle.RenderTransform>
                                                    <TranslateTransform x:Name="R1TT"/>
                                                </Rectangle.RenderTransform>
                                            </Rectangle>
                                            <Rectangle Fill="{TemplateBinding Foreground}" Height="4" IsHitTestVisible="False" Width="4" x:Name="R2" Opacity="0" CacheMode="BitmapCache">
                                                <Rectangle.RenderTransform>
                                                    <TranslateTransform x:Name="R2TT"/>
                                                </Rectangle.RenderTransform>
                                            </Rectangle>
                                            <Rectangle Fill="{TemplateBinding Foreground}" Height="4" IsHitTestVisible="False" Width="4" x:Name="R3" Opacity="0" CacheMode="BitmapCache">
                                                <Rectangle.RenderTransform>
                                                    <TranslateTransform x:Name="R3TT"/>
                                                </Rectangle.RenderTransform>
                                            </Rectangle>
                                            <Rectangle Fill="{TemplateBinding Foreground}" Height="4" IsHitTestVisible="False" Width="4" x:Name="R4" Opacity="0" CacheMode="BitmapCache">
                                                <Rectangle.RenderTransform>
                                                    <TranslateTransform x:Name="R4TT"/>
                                                </Rectangle.RenderTransform>
                                            </Rectangle>
                                            <Rectangle Fill="{TemplateBinding Foreground}" Height="4" IsHitTestVisible="False" Width="4" x:Name="R5" Opacity="0" CacheMode="BitmapCache">
                                                <Rectangle.RenderTransform>
                                                    <TranslateTransform x:Name="R5TT"/>
                                                </Rectangle.RenderTransform>
                                            </Rectangle>
                                        </Grid>
                                    </Border>
                                </Grid>
                            </unsupported:RelativeAnimatingContentControl>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

    在上面的Style里,ProgressBar的进度动画被封装在VisualStateGroup里,动画类型是DoubleAnimation,凡是DoubleAnimation的动画都会自动在Composite Thread上执行,从而做到不卡UI线程,Silverlight的动画就是在一个时间轴上不停改变依赖属性的值,也就是只要是动画Double类型的依赖属性(比如动画TranslateTransform X Y的值,动画UI的Opacity透明度),那么这些动画都会转到Composite Thread上执行。

    总结

    Composite Thread的存在是为了从UI线程剥离DoubleAnimation动画出来,提高UI快速响应能力。

    DoubleAnima类型的动画会自动在Composite Thread上运行。

    开发WP7时候,要用Toolkit下的PerformanceProgressBar替代系统的自带的ProgressBar来获得更好的UI体验。

  • 相关阅读:
    [extjs] ExtJs4.2 Form 表单提交
    [java ] java.util.zip.ZipException: error in opening zip file
    Oracle 11g 执行计划管理1
    Oracle 分区表的统计信息实例
    Oracle 手动收集统计信息
    Oracle 10g 之自动收集统计信息
    Oracle 11g 之自动收集统计信息
    Oracle 11gR2 RAC修改SCAN IP
    共享内存shared pool (6):追踪sql语句
    共享内存shared pool (5):详解一条SQL在library cache中解析
  • 原文地址:https://www.cnblogs.com/xinbaby/p/xinbaby_WindowsPhone_Composite_Thread.html
Copyright © 2011-2022 走看看