Bitva s OutOfMemoryException během vývoje uživatelského rozhraní

Václav Dajbych       5. 6. 2013       Windows Phone       5000 zobrazení

Při vývoji WPF aplikací pro Windows Phone či Windows Store se celkem snadno setkávám s OutOfMemoryException. Pokud se snažím zobrazit hodně dat a tuto výjimku je schopné odchytit Visual Studio, je příčina zcela určitě ve velké paměťové náročnosti ovládacích prvků uživatelského rozhraní. Projevuje se to zejména na zařízeních s malou pamětí a s procesorem architektury ARM. V tomto článku ukážu, jak se s tím dá vypořádat.

Vše bude jednou textura

Každý ovládací prvek na platformě Windows Phone nesmí být širší nebo vyšší než 2048 pixelů. Víte, proč tomu tak je? Protože ovládací prvek je ve finále textura a je jedno, jestli se jedná o Image nebo o TextBlock. Textura zabírá poměrně velké množství paměti, protože to je bitmapa. Je to řádově víc, než je velikost obrázku uloženého jako soubor na disku. Jako soubor je totiž obrázek komprimován. Může se jednat o metody jednoduché jako PNG, složité jako například JPEG a velmi komplexní jako JPEG XR. Obrázek se komprimuje hlavně proto, aby byl jeho přenos ze serveru na klienta co možná nejrychlejší. Na úrovni vykreslování na displej je ale všechno bitmapa, protože se dá pracovat jen s touto reprezentací.

V paměti jsou textury všech ovládacích prvků okna

Pojmem okno myslím v tomto článku rodičovský element deklarovaný jazykem XAML. Většinou se jedná o PhoneApplicationPage či LayoutAwarePage. Jazyk XAML se stejně překládá do jazyka C# a nakonec vznikne něco, co je prakticky totožné s tím, co generuje Visual Studio do code behindu pokud navrhujete Windows Forms aplikaci. Ostatně i v případě XAML aplikace se tyto kódy se nachází v adresáři obj/Debug a můžete si je kdykoliv prohlédnout.

Podstatné je, že se v paměti drží všechno, co okno může zobrazit. Slovem může myslím cokoliv, co není vidět, ale uživatel se na to může posunout. Jsou to všechny položky ovládacích prvků jako ListBox, Pivot, nebo GridView. Kdykoliv nastavuji binding na vlastnosti ItemsSource, zamýšlím se nad tím, jestli počet prvků bude řádově v desítkách. Pokud jich může být víc, není myslitelné vytvářet ovládací prvky pro všechny položky. A to je právě to, k čemu je vynikající DataTemplate a proč je tak snadné se dostat do paměťového stresu.

Řešení může být poměrně snadné, ale vždy to záleží na konkrétním případu. Někdy stačí jen nastavovat vlastnost Visibility na hodnotu Collapsed. Proto by správně nadpis této části měl znít: V paměti jsou textury všech ovládacích prvků okna, které mají nastavenou vlastnost Visibiliy na hodnotu Visible.

Pryč s ovládacími prvky

V některých případech však okolnosti vyžadují implementaci vlastního ovládacího prvku. Není třeba se ničeho obávat, většinou to je mnohem rychlejší a nakonec i lepší, než se snažit ohnout nějaký jiný ovládací prvek, aby vypadal tak, jak je zrovna potřeba. V naprosté většině případů stačí vyjít ze třídy UserControl. Přímé vykreslování přes třídu Graphics (což je obal GDI+) jsem potřeboval, jen když jsem si chtěl udělat plynulou animaci ve Windows Forms. Vlastní ovládací prvek tedy stačí udělat tak, aby obsahoval co možná nejmenší počet svých vlastních ovládacích prvků. Aby se zkrátka uživatel nepohyboval po ovládacích prvcích, ale datových kontextech ovládacích prvků.

image001

Obrázek nahoře znázorňuje prvky v paměti při použití běžné techniky. Pro každý DataContext se vytvoří ovládací prvek podle DataTemplate.

image002

Tento obrázek vyjadřuje úsporu paměti oproti minulému případu. Již se nevytváří ovládací prvek pro každý ViewModel, ale jsou jen statické ovládací prvky, kterým se mění jejich DataContext.

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

 

 

Nový příspěvek

 

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback