Get Microsoft Silverlight

Friday, May 13, 2011

WP7Dev Tip 2– Few things to remember on Image handling

Image handling is an important factor deciding the performance as well as usability of any application. When it comes to Windows Phone 7 it is even more important because of the limited network conditions and the low processing power as compared to PC.
Here is the video I am talking about the same things with a Bing Search sample in Silverlight TV show

I am just listing down few common tips which can greatly improve the performance and effectiveness of your application. And also please note that some of the points might not be applicable for certain applications especially for very small apps.
  • Use JPEG instead of PNG whenever possible – Jpeg decodes faster than PNG image.  If there is no transparency needed, use Jpeg with a compromised quality
  • Optimize your static Image quality :  Medium quality compressed Jpeg requires less memory to render as compared to a full quality Jpeg. So there is a big savings in memory and performance, if we can compromise on the Jpeg quality slightly. I am pasting two images below, one is 100% and the other is 97% quality, you can hardly make out the difference so the gist of it from a file size perspective is that the 97% one takes only half the size of the 100% image(108KB and 58Kb) ( of course the size and compression varies depends on the color information of the images). Now if you have got so many static images in the project, this trick can reduce the XAP file size considerably smaller as well as runtime memory usage will be quite less. You can consider this tip when you use large background images like Page/Panorama/Pivot background or splash screen images etc..
                   Penguins  Penguins97
  • Use images instead of complex gradients or vector graphics(XAML).
  • Never bind server-hosted images directly to the <Image> control, because Silverlight runtime will use the UI thread (using WebClient) to fetch that image from the server, that can make the UI unresponsive for some time.
  • Use a background thread and HttpWebRequest class based implementation to download the image data in an efficient way which finally creates BitmapImage and sets that as the source. A clean MVVM wrapper around this would make your entire Image management pretty easy.
  • When large scrollable list boxes need preview again don’t use vector/gradients instead use small Jpeg/png, that helps the system level caching effectively and improve the performance of scrolling.
  • Never let any image downloads happening while scrolling : Image downloading on long Listboxes should be controlled by the ScrollViewer state and position to optimize the network activity and also it would be effective to download the images in a queue based background thread system. This will ensure scrolling performance by downloading only the visible set of images, that too only when the scrolling activity stops.
In the below code snippet I have a collection of ViewModel instances bound to a ListBox and the ListBox has a ScrollViewer in its control template. We need to do two things to make sure there is no unnecessary image download happening 1) Detect the scroll stop event  2) Calculate the scroll position to find out the range of items which are visible to the user. Our aim is to just download the images associated with the ViewModels of that particular range when the scroll operation stops.
I am using the code snippet from Peter Torr’s blog for detecting the Scroll state and applying some easy math to find out the index range. Here I am assuming my Collection class has  some method to do the Queued image download in background thread with the signature void LoadImages(int startIndex, int count)
In the code snippet you can also see the place where we can detect the scroll end. That is very useful for pagination scenarios to download the next set of data from the service.

Please take a look at the source code, that shows the image download in a background thread and the visible range of visuals getting downloaded when we stop scrolling.

Have fun with Wp7 development!

Monday, March 21, 2011

WP7Dev Tip 1– Optimizing the app by reusing already created visuals

Developing a good application in the phone need not be accompanied with so much of hacking around or doing lot of non-conventional tricks. Most of the time those tricks make us deviate from the regular ways of development, make the code ugly and unmaintainable.  If we can get a sense of the pain-points and limitations of the platform early, then find a way around it and separate those concerns out of your business logic so as to proceed with a smooth development. I am explaining a pretty basic yet useful idea of how to reuse the complex visuals you have already created in previous pages of the application at runtime. Please note that this may not be applicable to small applications involving two or three pages of total navigation.
Problem : Imagine you have an application which needs to navigate to the same view over and over again. For example the Movie details page of IMDb or Netflix app, or profile page of Facebook or Twitter, those pages get called many times in the life span of an application instance. If we approach it in a standard way of putting a Panorama/Pivot inside a PhoneApplicationPage say MovieDetails.xaml, then each time we go to that page, creates a new instance of the page. Also it creates totally new Pano/Pivot in the visual tree under that page and when you navigate away, that gets pushed to the navigation stack. Suppose this pano when it gets rendered takes up 20MB( IMDb app got more good resolution images in a pano and one MovieDetails took around 20MB to render), so when we navigate to 5 different movies the app holds up a 100MB memory footprint. Since Garbage collection is a lazy operation, that memory wont get easily released. And as you know the platform will kill the app because it reached an unacceptable memory level.
Solution : So now we are clear on one thing, we don’t need to recreate that pano over and over. Because when the first movie details showed up the system did a hard job of creating all those visuals in memory. So it is a matter or showing that pano visual again with a totally different Movie as its new DataContext.
Technical Solution : It is pretty easy to solve this by treating the PhoneApplicationPage as merely a Content placeholder. We can do it in many ways, in my design I have kept only one xaml phonepage and put a special Layout panel (say Grid) in it. And depending on the ViewModel type to be displayed we can always instantiate a DataTemplate(the Pano will be a MovieDetailsDataTemplate in this case) and add that UIElement in to the layout. This operation can be at the PhoneApplicationPage.NavigatedTo() override. Now when this page is navigated away (NavigatedFrom()) we can easily remove that particular UIElement from the layout/page and keep it in the memory. So the next time when it demands a similar view, it will just get loaded back from the memory on to another page instance. This way, all the page instances going to the navigation stack would be pretty much a ‘dummy’ container and wouldn’t hold up any memory at all.
Result : With out this approach we could go only 5 or 6 ‘Movie –> Actor –> Movie’ loops, now we can do 100s of page navigations on that movie-actor loop ( Check out the IMDb app)
And there are many other advantages of keeping a single PhoneapplicationPage class for the entire app, I will be explaining it in my next blog