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:

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 ListViewby 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:

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í.