The performance optimization of Phone (two) Windows

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

This article is in the demo (a) on the basis of the adjustment, the basic logic similar. This paper only columns and a different code.


In order to virtual realization of custom, the last article of ListBox into ScrollViewer + ItemsControl, this combination in the actual project

Such as is or will be used,, if we need quite a lot of control of ScrollViewer, such as access to its "sliding" event, ScrollViewer

Other controls in place, or customize its style and so on (of course may through the VisualTreeHelper can access ListBox in ScrollViewer).


ListBox (derived from ItemsControl) internal implementation is encapsulated in ScrollViewer + ItemsControl control, in this demo, the use of combination:

            <ScrollViewer x:Name="scrollViewer" Loaded="ScrollViewer_Loaded">
                <ItemsControl x:Name="listbox" ItemsSource="{Binding}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <!--Although the setting for "virtual panel", but it is not the virtual function-->
                            <VirtualizingStackPanel/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal" Margin="10,30,0,0">
                                <Image VerticalAlignment="Top" Source="{Binding Photo}" Width="150"/>
                                <TextBlock Text="{Binding Title}" Width="250" Foreground="Wheat"
FontSize="25" Margin="10,0,0,0" TextWrapping="Wrap"/> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </ScrollViewer>


On the basis of an demo, when loaded with 200 data, running in the 1G simulator, memory footprint to 200+MB,

If the 512MB simulator, haven't finished loading data, application crash:


Optimization algorithm

Following the principles of demo is very simple, is that when an item in the list, when on the screen, the Visibility is set to Visibility.Visible,

When out of the screen, set to Visibility.Collapsed; logic is very simple, but the occupation of memory decrease. However, in order to users

If the user experience, also is sliding list to the screen where it projects, not timely display, in the user's point of view, is very depressed, so

An algorithm to check whether the current list on the screen.

Train of thought:




On the other part of the demo code please refer to the previous article.

1)First put a button in the XAML page, as shown above, when the application is loaded, the default fine any treatment, when you click the "virtual" button,

Trigger custom virtual methods, pages Xaml:

<Button Content="Virtualization" HorizontalAlignment="Left" Margin="335,0,0,0"
VerticalAlignment="Top" Width="133" Height="72" Tap="Button_Tap"/>


The corresponding C#:

        //When the user clicks the button, virtual simulation
        private void Button_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            e.Handled = true;

            Visualizition();
        }


2)When the little button, first get the list, all replication by DataTemplate StackPanel in each item. Because ListBox inherits from ItemsControl,

And their ItemContainerGenerator properties of the ContainerFromIndex (int index) method can obtain the list of designated Item, followed by the

VisualTreeHelper static methods, obtain the template generated StackPanel. All of the code:

        void Visualizition()
        {
            // The custom of a "dictionary", used to store each Y coordinates and its references to "itself"
            Dictionary<double, StackPanel> dic = new Dictionary<double, StackPanel>();

            double height_sum = 0;
            for (int i = 0; i <listbox.Items.Count; i++)
            {
                // Because ListBox is a list of generated through data binding, so need to get through ItemContainerGenerator
                // Each StackPanel of the parent control
                FrameworkElement fe = listbox.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
                StackPanel sp = FindFirstElementInVisualTree<StackPanel>(fe);
                
                dic.Add(height_sum, sp);

                // Cumulative Y highDegree
// 30 for the parent container template margin-top
height_sum = height_sum + sp.ActualHeight + 30; // Set the height of their true height
// Is very important, if you do not specify a fixed height parent container, if the elements hidden, the parent container height to 0px
sp.Height = sp.ActualHeight; } // Every 0.5 seconds, loop checking a list, which items on the screen, if you display on the screen, and, if // In the screen, then the hidden Observable.Interval(TimeSpan.FromSeconds(.5)).ObserveOnDispatcher().Subscribe((_) => { foreach (var keyValue in dic) { if (((scrollViewer.VerticalOffset - 500) > keyValue.Key || keyValue.Key > (scrollViewer.VerticalOffset + 900))) { keyValue.Value.Children[0].Visibility = System.Windows.Visibility.Collapsed; keyValue.Value.Children[1].Visibility = System.Windows.Visibility.Collapsed; } else { keyValue.Value.Children[0].Visibility = System.Windows.Visibility.Visible; keyValue.Value.Children[1].Visibility = System.Windows.Visibility.Visible; } } }); } // Find the "tree" in the control private T FindFirstElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject { var count = VisualTreeHelper.GetChildrenCount(parentElement); if (count == 0) return null; for (int i = 0; i <count; i++) { var child = VisualTreeHelper.GetChild(parentElement, i); if (child != null && child is T) { return (T)child; } else { var result = FindFirstElementInVisualTree<T>(child); if (result != null) return result; } } return null; }


When loading 200 news, run the project effect:


The above algorithm is every 0.5 seconds to traverse a Dictionary keys, to directly without re optimization. For example, each traversal time,

The screen visual area.


The default runtime, memory usage of 208MB effect:


Click the button, when sliding up and down, can see the delay display item, memory to reduce the number of:



In addition, I think you can use Quick sort The algorithm can quickly find new method, sliding to the screen in Item, before the screen of the Item

If still in the screen, skip, etc.. About how to optimize the above algorithm here is not to say. Because the project is to reduce the memory in the introduction

Ideas, so are not considered in the application in the "how to load more..", how to add new item and so on the actual interaction again.


There is on the Reactive Extension class library (has been integrated in the WP8 SDK used here), but also introduce more, it

It is a wonderful thing, the garden has written articles related to friends, some time ago I also translate it (the link), later finishing

More articles about Rx. Here the use of Observable as a timer, of course, can also be customized Timer, Observable use up feeling

More convenient.


In the above code: Observable.Interval (TimeSpan.FromSeconds (.5)).ObserveOnDispatcher (.Subscribe (=>) (_) {// omitted; });

The meaning is, every 0.5 seconds, registered in the UI Xian Chengzhong method called a Subscribe.



Extension

Through the demo, developers should be aware that, on the page, as little as possible to draw the element, for the performance of Windows Phone application promotion, for memory

Optimization, how obvious. For example, try to reduce the UI controls nested; in the Pivot (or Panorama) page items in the control, without PivotItem.

The current screen, then put it on Child set to hide, when the user switches to the PivotItem page, to show it. Wait.



In this paper, demo download

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Ron at December 09, 2013 - 5:25 AM