Výkon Xamarin.Android

Existuje mnoho technik pro zvýšení výkonu aplikací sestavený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 projevuje mnoha způsoby. Může se zdát, že aplikace nereaguje, může způsobit pomalé posouvání a snížit životnost baterie. Optimalizace výkonu ale zahrnuje více než jen implementaci efektivního kódu. Je také třeba zvážit zkušenosti uživatele s výkonem aplikace. Například zajištění, že se operace provádějí bez blokování, aby uživatel mohl provádět jiné aktivity, může pomoct zlepšit uživatelské prostředí.

Existuje řada technik pro zvýšení výkonu a vnímaní výkonu aplikací sestavených pomocí Xamarin.Android. Mezi ně patří:

Poznámka

Než si přečtete tento článek, měli byste si nejprve přečíst článek Výkonnapříč platformami, který popisuje jiné než platformové techniky pro zlepšení využití paměti a výkonu aplikací sestavený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řování instancí, které používají parametr , protože každý podřízený objekt LinearLayoutweight se bude měřit dvakrát. Použití vnořených instancí třídy může vést k hierarchii hloubkových zobrazení, což může vést ke špatnému výkonu rozložení, která jsou nafoukána vícekrát, například v LinearLayoutListView objektu . Proto je důležité, aby byla taková rozložení optimalizovaná, protože se následně vynásobí výkonové výhody.

Představte si například řádek zobrazení seznamu, který má LinearLayout ikonu, název a popis. LinearLayoutobjekt bude obsahovat a ImageView svislou LinearLayout čárku, která TextView obsahuje dvě 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í každého řádku je ListView plýtvání. Můžete ho ale vylepšit zploštěte rozložením, 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-level hierarchie byla snížena na dvou úrovní hierarchie a jedna RelativeLayout nahradila LinearLayout dvě instance. Výrazné zvýšení výkonu se zvýší při nafouknutí rozložení pro každý ListView řádek.

Optimalizace zobrazení seznamu

Uživatelé očekávají u instancí plynulé posouvání a ListView rychlé načítání. Výkon posouvání ale může utrpět, pokud 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, abyste se vyhnuli špatnému ListView výkonu:

  • Opakované použití zobrazení řádků Další informace najdete v tématu Opětovné použití zobrazení řádků.
  • Pokud je to možné, zploštěte rozložení.
  • Ukládání obsahu řádků do mezipaměti, který se načítá z webové služby
  • Vyhněte se škálování obrázků.

Tyto techniky společně pomáhají udržovat plynulé ListView posouvání instancí.

Opakované použití zobrazení řádků

Při zobrazení stovek řádků v objektu by bylo plýtvání pamětí při vytváření stovek objektů, pokud se na obrazovce zobrazí pouze malý ListViewView počet objektů najednou. Místo toho lze do paměti načíst pouze objekty viditelné v řádcích na obrazovce a obsah se načte do těchto opětovně View využitých objektů. View To brání vytváření instancí stovek dalších objektů a šetří čas a paměť.

Proto když řádek z obrazovky zmizí, může se jeho zobrazení 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;
}

Při posouvání uživatel volá přepsání , aby si vyžádal nová zobrazení, která se zobrazí – pokud je k dispozici, předá v parametru nepoužívané ListViewGetViewconvertView zobrazení. Pokud je tato null hodnota , kód vytvoří novou instanci, jinak je možné vlastnosti resetovat a znovu ViewconvertView použít.

Další informace najdete v tématu Opětovné použití zobrazení řádků při naplnění objektu ListView daty.

Odebrání obslužných rutin událostí v aktivitách

Když je aktivita zničena v modulu runtime Androidu, stále může být aktivní v Mono runtime. Proto odeberte obslužné rutiny událostí pro externí objekty v , aby se zabránilo modulu runtime zachovat odkaz na Activity.OnPause 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ěť nelze stránkovat ani používat jinde. Ponechání služby spuštěné, když není potřeba, proto zvyšuje riziko, že aplikace vykazuje nízký výkon z důvodu omezení 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 se může omezit použitím , která se ukončí, jakmile zřemezuje IntentService záměr, který ji zahájil.

Uvolnění prostředků při oznámení

Během životního cyklu aplikace zpětné OnTrimMemory volání zobrazí oznámení, když je nedostatek paměti zařízení. Toto zpětné volání by mělo být implementováno, aby naslouchaly 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í obdržet následující oznámení na úrovni OnTrimMemory paměti:

  • TrimMemoryBackground – uvolní prostředky, které lze rychle a efektivně znovu vytvořit, pokud se uživatel vrátí do aplikace.
  • TrimMemoryModerate – uvolnění prostředků může systému pomoct zachovat v mezipaměti další procesy, aby se lépe celkového výkonu.
  • TrimMemoryComplete – Proces aplikace se brzy ukončí, pokud se brzy nezochová více paměti.

Oznámení by měla být odsouzena uvolněním prostředků na základě přijaté úrovně.

Uvolnění prostředků, 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 dostávat oznámení, když uživatel ukončí uživatelské rozhraní, implementujte zpětné volání ve třídách a naslouchejte úrovni, která označuje, že je uživatelské rozhraní skryté OnTrimMemoryActivity před TrimMemoryUiHidden zobrazením. Toto oznámení bude přijato pouze v případě, že se uživateli skrýjí všechny součásti uživatelského rozhraní aplikace. Uvolnění prostředků uživatelského rozhraní při přijetí tohoto oznámení zajistí, že pokud se uživatel vrátí z jiné aktivity v aplikaci, budou prostředky uživatelského rozhraní stále dostupné pro rychlé obnovení aktivity.

Optimalizace prostředků obrázků

Image jsou některé z nejdražších prostředků, které aplikace používají, a často se zachycují ve vysokém rozlišení. Proto se při zobrazení obrázku zobrazí v rozlišení požadovaném pro obrazovku zařízení. Pokud má obrázek vyšší rozlišení než obrazovka, měli byste ho škálovat dolů.

Další informace najdete v tématu Optimalizace prostředků obrázků vprůvodci výkonem pro více platforem.

Uvolnění nepoužívaných prostředků image

Pokud chcete ušetřit na využití paměti, je vhodné se zbavit velkých prostředků image, které už nepotřebujete. Je však důležité zajistit, aby byly image správně odstraněny. Místo explicitního vyvolání můžete k zajištění správného používání objektů využít příkazy .Dispose().Dispose()IDisposable using.

Například třída Bitmap implementuje . Zabalením instance objektu do bloku zajistíte jeho správné uvolnění BitMapusing 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í uvolnitelných prostředků najdete v tématu Release IDisposable Resources.

Vyhněte Floating-Point aritmetickému

Na zařízeních s Androidem je aritmetika s plovoucí desetinnou čárkou přibližně 2krát pomalejší než celočíselná aritmetika. Proto pokud je to možné, nahraďte aritmetické operace s plovoucí desetinnou čárkou celočíselnou aritmetou. Nejedná se však o rozdíl mezi časem spuštění float a double aritmetickým vlivem na nedávném hardwaru.

Poznámka

I pro aritmetické aritmetické operace některé procesory nemají funkce rozdělení hardwaru. Proto se v softwaru často provádí operace dělení celých čísel a zbytků.

Zavřít dialogová okna

Při použití ProgressDialog třídy (nebo jakéhokoli dialogového okna nebo výstrahy) místo volání Hide metody, když je účel dialogu volán, zavolejte Dismiss metodu. V opačném případě bude dialogové okno pořád aktivní a tato činnost se nevrátí, když drží odkaz na něj.

Souhrn

Tento článek popisuje a popisuje techniky pro zvýšení výkonu aplikací vytvořených pomocí Xamarin. Android. Souhrnně tyto techniky můžou významně snížit množství práce prováděné CPU a množství paměti, které aplikace spotřebovává.