Výkon Xamarin.Android
Existuje mnoho technik pro zvýšení výkonu aplikací vytvořených pomocí Xamarin.Android. Souhrnně tyto techniky mohou výrazně snížit množství práce prováděné procesorem a množství paměti spotřebované aplikací. Tento článek popisuje a popisuje tyto techniky.
Přehled výkonu
Nízký výkon aplikace se prezentuje mnoha způsoby. Aplikace může vypadat jako nereagující, může způsobit pomalé posouvání a může snížit životnost baterie. Optimalizace výkonu ale zahrnuje nejen implementaci efektivního kódu. Je také potřeba zvážit zkušenosti uživatele s výkonem aplikace. Například zajištění toho, aby se operace spouštěly bez blokování uživatele v provádění dalších aktivit, můžou pomoct zlepšit uživatelské prostředí.
Existuje řada technik pro zvýšení výkonu a vnímaného výkonu aplikací vytvořených pomocí Xamarin.Androidu. Patří sem:
- Optimalizace hierarchií rozložení
- Optimalizace zobrazení seznamu
- Odebrání obslužných rutin událostí v aktivitách
- Omezení životnosti služeb
- Prostředky vydaných verzí při oznámení
- Prostředky vydaných verzí, když je uživatelské rozhraní skryté
- Optimalizace prostředků image
- Odstranění nepoužívaných prostředků image
- Vyhněte se Aritmetické aritmetice s plovoucí desetinou čárkou
- Zavřít dialogy
Poznámka:
Než si přečtete tento článek, měli byste si nejprve přečíst výkon pro různé platformy, který popisuje jiné než platformy specifické techniky ke zlepšení využití paměti a výkonu aplikací vytvořených pomocí platformy Xamarin.
Optimalizace hierarchií rozložení
Každé rozložení přidané do aplikace vyžaduje inicializaci, rozložení a kreslení. Předání rozložení může být nákladné při vnoření LinearLayout
instancí, které tento parametr používají weight
, protože každé podřízené nastavení se bude měřit dvakrát. Použití vnořenýchinstancích LinearLayout
služeb může vést k hierarchii hloubkového zobrazení, což může vést k nízkému výkonu rozložení, která jsou vícekrát nafoukaná, například v ListView
. Proto je důležité, aby se taková rozložení optimalizovala, protože výhody výkonu se pak vynásobí.
Představte si LinearLayout
například řádek zobrazení seznamu s ikonou, názvem a popisem. Bude LinearLayout
obsahovat svislou ImageView
a svislou LinearLayout
hodnotu, která obsahuje dvě TextView
instance:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="5dip">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="5dip"
android:src="@drawable/icon" />
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="Mei tempor iuvaret ad." />
<TextView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
android:text="Lorem ipsum dolor sit amet." />
</LinearLayout>
</LinearLayout>
Toto rozložení je 3 úrovně hluboké a při nafouknutí jednotlivých ListView
řádků je plýtvání. Můžete ho ale vylepšit zploštěním rozložení, jak je znázorněno v následujícím příkladu kódu:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="5dip">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="5dip"
android:src="@drawable/icon" />
<TextView
android:id="@+id/secondLine"
android:layout_width="fill_parent"
android:layout_height="25dip"
android:layout_toRightOf="@id/icon"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:singleLine="true"
android:ellipsize="marquee"
android:text="Lorem ipsum dolor sit amet." />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/icon"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_above="@id/secondLine"
android:layout_alignWithParentIfMissing="true"
android:gravity="center_vertical"
android:text="Mei tempor iuvaret ad." />
</RelativeLayout>
Předchozí 3úrovňová hierarchie byla snížena na dvouúrovňovou hierarchii a jedna RelativeLayout
nahradila dvě LinearLayout
instance. Při nafouknutí rozložení pro každý ListView
řádek se získá významné zvýšení výkonu.
Optimalizace zobrazení seznamu
Uživatelé očekávají hladké posouvání a rychlé načítání ListView
instancí. Výkon posouvání však může mít za to, že každý řádek zobrazení seznamu obsahuje hluboko vnořené hierarchie zobrazení nebo když řádky zobrazení seznamu obsahují složitá rozložení. Existují však techniky, které lze použít k zabránění nízkému ListView
výkonu:
- Další informace najdete v tématu Opětovné použití zobrazení řádků.
- Pokud je to možné, zploštěné rozložení.
- Obsah řádku mezipaměti načtený z webové služby
- Vyhněte se škálování obrázků.
Tyto techniky společně můžou pomoct zajistit ListView
bezproblémové posouvání instancí.
Opakované použití zobrazení řádků
Při zobrazení stovek řádků v objektu ListView
by to bylo plýtvání pamětí k vytvoření stovek View
objektů, když se na obrazovce najednou zobrazí jen malý počet. Místo toho lze do paměti načíst pouze View
objekty viditelné v řádcích na obrazovce, přičemž obsah načtený do těchto opakovaně využitých objektů. Tím se zabrání vytvoření instance stovek dalších objektů, což šetří čas a paměť.
Proto když řádek zmizí z obrazovky, jeho zobrazení lze umístit do fronty pro opakované použití, jak je znázorněno v následujícím příkladu kódu:
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView; // re-use an existing view, if one is supplied
if (view == null) // otherwise create a new one
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
// set view properties to reflect data for the given row
view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = items[position];
// return the view, populated with data, for display
return view;
}
Když se uživatel posune, ListView
zavolá GetView
přepsání pro vyžádání nových zobrazení k zobrazení – pokud je k dispozici, předá nepoužívané zobrazení v parametru convertView
. Pokud je null
tato hodnota, kód vytvoří novou View
instanci, jinak convertView
lze vlastnosti resetovat a znovu použít.
Další informace naleznete v tématu Opětovné použití zobrazení řádků při naplnění ListView daty.
Odebrání obslužných rutin událostí v aktivitách
Když je aktivita zničena v modulu runtime Androidu, může být stále aktivní v modulu runtime Mono. Proto odeberte obslužné rutiny událostí externím Activity.OnPause
objektům, aby zabránil modulu runtime v zachování odkazu na aktivitu, která byla zničena.
V aktivitě deklarujte obslužné rutiny událostí na úrovni třídy:
EventHandler<UpdatingEventArgs> service1UpdateHandler;
Pak implementujte obslužné rutiny v aktivitě, například v OnResume
:
service1UpdateHandler = (object s, UpdatingEventArgs args) => {
this.RunOnUiThread (() => {
this.updateStatusText1.Text = args.Message;
});
};
App.Current.Service1.Updated += service1UpdateHandler;
Když aktivita ukončí spuštěný stav, OnPause
je volána. V implementaci OnPause
odeberte obslužné rutiny následujícím způsobem:
App.Current.Service1.Updated -= service1UpdateHandler;
Omezení životnosti služeb
Když se služba spustí, Android udržuje proces služby spuštěný. Díky tomu je proces nákladný, protože jeho paměť se nedá stránkovat ani použít jinde. Ponechání služby spuštěné v případě, že není potřeba, zvyšuje riziko aplikace, která vykazuje nízký výkon kvůli omezením paměti. Může také snížit efektivitu přepínání aplikací, protože snižuje počet procesů, které může Android ukládat do mezipaměti.
Životnost služby může být omezena použitím IntentService
, která se ukončí, jakmile se zpracuje záměr, který ji spustil.
Prostředky vydaných verzí při oznámení
Během životního cyklu OnTrimMemory
aplikace poskytuje zpětné volání oznámení, když je paměť zařízení nízká. Toto zpětné volání by mělo být implementováno pro naslouchání následujícím oznámením na úrovni paměti:
TrimMemoryRunningModerate
– aplikace může chtít uvolnit některé nepotřebné prostředky.TrimMemoryRunningLow
– aplikace by měla uvolnit nepotřebné prostředky.TrimMemoryRunningCritical
– aplikace by měla uvolnit tolik nekritičtějších procesů, kolik může.
Kromě toho při ukládání procesu aplikace do mezipaměti může zpětné volání přijímat OnTrimMemory
následující oznámení na úrovni paměti:
TrimMemoryBackground
– uvolněte prostředky, které se dají rychle a efektivně znovu vytvořit, pokud se uživatel vrátí do aplikace.TrimMemoryModerate
– uvolnění prostředků může systému pomoct udržet ostatní procesy uložené v mezipaměti pro lepší celkový výkon.TrimMemoryComplete
– proces aplikace se brzy ukončí, pokud se brzy neobnoví více paměti.
Oznámení by měla být zodpovězena uvolněním prostředků na základě přijaté úrovně.
Prostředky vydaných verzí, když je uživatelské rozhraní skryté
Uvolněte všechny prostředky používané uživatelským rozhraním aplikace, když uživatel přejde do jiné aplikace, protože může výrazně zvýšit kapacitu Androidu pro procesy uložené v mezipaměti, což může mít vliv na kvalitu uživatelského prostředí.
Pokud chcete obdržet oznámení, když uživatel ukončí uživatelské rozhraní, implementujte OnTrimMemory
zpětné volání do Activity
tříd a poslouchejte TrimMemoryUiHidden
úroveň, která indikuje, že uživatelské rozhraní je skryté v zobrazení. Toto oznámení bude přijato pouze v případě, že se všechny součásti uživatelského rozhraní aplikace uživateli skryje. Uvolnění prostředků uživatelského rozhraní při přijetí tohoto oznámení zajistí, že pokud uživatel přejde zpět z jiné aktivity v aplikaci, budou prostředky uživatelského rozhraní stále k dispozici pro rychlé obnovení aktivity.
Optimalizace prostředků image
Obrázky jsou některé z nejdražších prostředků, které aplikace používají, a často se zaznamenávají ve vysokém rozlišení. Proto při zobrazení obrázku ho zobrazte v rozlišení požadovaném pro obrazovku zařízení. Pokud má obrázek vyšší rozlišení než obrazovka, mělo by se vertikálně snížit jeho kapacitu.
Další informace najdete v tématu Optimalizace prostředků image v průvodci výkonem napříč platformami.
Odstranění nepoužívaných prostředků image
Pokud chcete ušetřit využití paměti, je vhodné zbavit se prostředků velkých imagí, které už nepotřebujete. Je však důležité zajistit, aby image byly správně uvolněny. Místo použití explicitního .Dispose()
vyvolání můžete využít použití příkazů k zajištění správného použití IDisposable
objektů.
Například Bitmap třída implementuje IDisposable
. Zabalení BitMap
instance objektu using
v bloku zajistí, že bude správně uvolněn při ukončení bloku:
using (Bitmap smallPic = BitmapFactory.DecodeByteArray(smallImageByte, 0, smallImageByte.Length))
{
// Use the smallPic bit map here
}
Další informace o uvolnění jednorázových prostředků naleznete v tématu Prostředky IDisposable vydané verze.
Vyhněte se Aritmetické aritmetice s plovoucí desetinou čárkou
Na zařízeních s Androidem je aritmetika s plovoucí desetinou čárkou přibližně o 2x pomalejší než celočíselná aritmetika. Proto pokud je to možné, nahraďte aritmetické aritmetické aritmetické čísly s plovoucí desetinou čárkou. V nedávném hardwaru ale není žádný rozdíl mezi float
aritmetickou double
dobou provádění.
Poznámka:
I u celočíselné aritmetické aritmetické funkce chybí některé procesory schopností dělení hardwaru. Proto jsou celočíselné operace dělení a modulu často prováděny v softwaru.
Zavřít dialogy
Při použití třídy (nebo jakéhokoli dialogového ProgressDialog
okna nebo výstrahy) místo volání Hide
metody při dokončení účelu dialogového okna zavolejte metodu Dismiss
. V opačném případě bude dialogové okno stále aktivní a bude nevratit aktivitu tím, že podrží odkaz na ni.
Shrnutí
Tento článek popisuje a popisuje techniky pro zvýšení výkonu aplikací vytvořených pomocí Xamarin.Androidu. Souhrnně tyto techniky mohou výrazně snížit množství práce prováděné procesorem a množství paměti spotřebované aplikací.