abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×

    dnes 11:33 | Nová verze

    Emulátor terminálu kitty (Wikipedie, GitHub) byl vydán v nové verzi 0.50.

    Ladislav Hagara | Komentářů: 0
    dnes 09:00 | Bezpečnostní upozornění

    Vývojáři C-Kermit oznámili několik dlouhodobě přítomných zranitelností. Patří mezi ně buffer overflow v Telnet/FTP klientovi a command injection v Kermit serveru. Dotčené verze: C-Kermit 11.0.514 a starší. Fix: 11.1.515 [oss-security].

    vencour | Komentářů: 0
    dnes 02:44 | Nová verze

    Byla vydána nová verze 3.2.8 svobodné aplikace pro úpravu a vytváření rastrové grafiky GIMP (GNU Image Manipulation Program). Přehled novinek v oznámení o vydání a v souboru NEWS na GitLabu. Nový GIMP je již k dispozici také na Flathubu.

    Ladislav Hagara | Komentářů: 0
    včera 16:55 | Nová verze

    Projekt openSUSE dnes, 3. listopadu 2026, oficiálně vydal openSUSE Leap 16.1, novou verzi své stabilní linuxové distribuce. Novinkou je také Immutable Mode, který nahrazuje dosavadní samostatnou distribuci openSUSE Leap Micro. Podrobnosti o novém vydání najdete v oficiálním oznámení nebo v českém překladu oznámení. Instalační obrazy jsou již dostupné na get.opensuse.org. Vydání společně oslavíme v pátek ve virtuálním baru a na … více »

    lkocman | Komentářů: 0
    včera 16:00 | Nová verze

    Bylo oznámeno vydání Fedora Linuxu 45. Ve finální verzi vychází šest oficiálních edic: Fedora Workstation a Fedora KDE Plasma Desktop pro desktopové, Fedora Server pro serverové, Fedora Cloud pro cloudové nasazení, Fedora CoreOS pro ty, kteří preferují neměnné systémy a Fedora IoT pro internet věcí. Vedle nich jsou k dispozici také další atomické desktopy, spiny a laby. Podrobný přehled novinek v samostatných článcích na stránkách

    … více »
    Ladislav Hagara | Komentářů: 1
    včera 15:44 | Zajímavý článek

    Vědci z MIT CSAIL představili koncept 'weight-space programming' a názorně předvedli, že pokročilé jazykové modely SI dokážou přímo číst a upravovat váhy neuronových sítí. Studie ukazuje, že modely nejen dokážou identifikovat účel sítí z pouhého nahlédnutí do jejich číselných vah, ale mohou i cíleně opravovat chyby a nedostatky, například GPT-6 Astra se změnou pouhých 0,016% vah open-weight modelu Qwen3.5-0.8B podařilo odstranit

    … více »
    👻 | Komentářů: 5
    včera 14:00 | Komunita

    Organizátoři komunitního setkání nejen českých a slovenských správců sítí CSNOG 2027, které se uskuteční 20. a 21. ledna na půdě zlínské univerzity Tomáše Bati, oznámili prodloužení termínu pro zasílání abstraktů do programu akce. Zájemci se mohou hlásit prostřednictvím webu setkání do úterý 10. listopadu. Programová komise uvítá příspěvky věnované nejen správě sítí, ale také legislativě a regulaci nebo síťařským aktivitám studentů a pedagogů.

    VSladek | Komentářů: 0
    včera 13:55 | IT novinky

    Bylo spuštěno předobjednávání zařízení Flipper One s Linuxem. Za 20 dolarů si lze koupit kupón a zajistit si tím speciální cenu 379 dolarů po spuštění kampaně na Kickstarteru.

    Ladislav Hagara | Komentářů: 0
    včera 12:44 | Nová verze

    Tor Browser, tj. fork webového prohlížeče Mozilla Firefox s integrovaným klientem sítě Tor přednastavený tak, aby přes tuto síť bezpečně komunikoval, byl vydán ve verzi 16.0. Postaven je na Firefoxu ESR 153. Vydána byla také nová verze 7.16 živé linuxové distribuce Tails (The Amnesic Incognito Live System), jež klade důraz na ochranu soukromí uživatelů a anonymitu. S Tor Browserem 16.0.

    Ladislav Hagara | Komentářů: 0
    včera 04:00 | Nová verze

    FreeTube, desktopový klient pro YouTube využívající lokální API, byl vydán ve verzi 0.26.0. Toto velké opravné vydání mj. vrací částečnou podporu živých přenosů nebo přepracovává zobrazování titulků a obecně nastavení videa v přehrávači – FreeTube umožňuje např. přehrávat video s větším zrychlením.

    ʚĭɞ 🍉 | Komentářů: 1
    Které desktopové prostředí na Linuxu používáte?
     (9%)
     (7%)
     (4%)
     (21%)
     (29%)
     (9%)
     (5%)
     (2%)
     (14%)
     (20%)
    Celkem 2973 hlasů
     Komentářů: 34, poslední 26.10. 08:24
    Rozcestník

    Vývoj pro Android – vylepšujeme aktivity

    5. 5. 2011 | Tomáš Kypta | Programování | 26897×

    Minule jsme si ukázali jednoduchou aplikaci složenou ze dvou aktivit. V tomto díle si příklad dále rozšíříme a ukážeme si nové konstrukty. Celkově probereme množství různých témat vztahujících se k aktivitám.

    Obsah

    Používání listů

    link

    Použití view prvků, které umí zobrazit větší množství dat, není úplně triviální. Takovými views, jež vyžadují použití adaptéru, jsou například ListView, Spinner, Gallery nebo GridView.

    Adaptér – třída vzniklá implementací interface Adapter – má funkci mostu mezi AdapterView (předek zmiňovaných views) a daty, která dané view zobrazují. Při použití ListView nám adaptér vytvoří most mezi seznamem položek a daty samotnými. Existuje několik abstraktních tříd adaptérů, jejichž poděděním snadno vytvoříte požadovanou funkcionalitu.

    Nyní se vrátíme k našemu minulému příkladu. V něm jsme si vytvořili dvě aktivity. K tomuto příkladu si přidáme třetí aktivitu SelectText, která bude zobrazovat seznam řetězců. Kliknutím na položku seznamu ji vybereme a vrátíme předešlé aktivitě.

    Vyvíjíme pro Android

    Aktivitu se seznamem lze vytvořit buď tak, že ji podědíme od třídy Activity a vytvoříme jednoduchý layout obsahující prvek ListView. Nebo lépe naši třídu podědíme od třídy ListActivity, která je připravená přesně pro tento účel a není třeba jí dodávat žádný layout definující obsah.

    Zdrojový kód aktivity SelectText bude tento:

    public class SelectText extends ListActivity {        
            public static String INTENT_BUNDLE_TEXT = "text";                
            public void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);                
                    setListAdapter(new SelectTextAdapter(this));                
                    ListView lv = getListView();                
                    lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                                    Intent appResultIntent = new Intent();
                                    appResultIntent.putExtra(INTENT_BUNDLE_TEXT, (String)parent.getItemAtPosition(position));
                                    setResult(RESULT_OK, appResultIntent);
                                    finish();
                            }
                    });                                          
            }        
    }
    

    Zde zavolání funkce onCreate() předka (ListActivity) způsobí nasetupování obsahu, což bychom jinak museli při použití vlastního layoutu dělat ručně. ListView, které je zde interně v ListActivity použito, se získá pomocí funkce getListView(). Pro přidání reakce na kliknutí na položku listu je třeba přidat OnItemClickListener, jeho použití je téměř identické jako v minulém příkladu u třídy ReturnText.

    Důležitý příkaz setListAdapter(new SelectTextAdapter(this)) nastavuje adaptér, jenž se bude starat o data. K vytvoření tohoto adaptéru použijeme abstraktní třídu BaseAdapter:

    public class SelectTextAdapter extends BaseAdapter {        
            private Context mContext;
            static final String[] texts = {"Android", "Google", "abclinuxu.cz"};
            public SelectTextAdapter(Context context) {
                    super();
                    this.mContext = context;
            }        
            public int getCount() {
                    return texts.length;
            }
            public Object getItem(int position) {
                    return texts[position];
            }
            public long getItemId(int position) {
                    return position;
            }
            public View getView(int position, View convertView, ViewGroup parent) {
                    LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    final TextView tv = (TextView)inflater.inflate(R.layout.select_text_item, null);
                    tv.setText((String)getItem(position));                                
                    return tv;
            }
    }
    

    Náš adaptér předává seznamu statické řetězce definované v kódu. Toto jistě není správný způsob, jak mít v aplikaci uložena data – jde pouze o zjednodušení. Lepší by bylo definovat si data v resources jako pole řetězců.

    SelectTextAdapter obsahuje konstruktor, který má jediný parametr, a to kontext. Rozhraní Context slouží k přístupu k aplikačním zdrojům. Context je velice často používaný, samotná třída Acitivity je jeho potomkem, lze tedy předávat referenci na aktuální aktivitu. Dále jsou zde čtyři funkce, jež je nutné naimplementovat. Poslední z nich, funkce getView(), vytváří views, které budou tvořit prvky seznamu. Pro vytvoření view z xml layoutu se používá třída LayoutInflater. Její instance se nikdy nevytváří přímo, místo toho se využívá instance, která se získá z contextu. Prvky seznamu jsou zde vytvořeny z jednoduchého layoutu select_text_item.xml. Ten obsahuje pouze jedno TextView:

    <?xml version="1.0" encoding="utf-8"?>
    <TextView
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
    </TextView>
    

    Spuštění této aktivity a zpracování jejího výsledku je naprosto identické jako u třídy ReturnText, kterou jsme si vytvořili minule. Nyní se přesuneme na nové téma.

    Dialogy

    link

    Občas bývá potřeba sdělit uživateli aplikace nějakou informaci nebo dostat jeho souhlas/odmítnutí. K takovému účelu se používají dialogy. Android nabízí jednak předdefinované jednoduché dialogy, ale také možnost vytvářet vlastní dialogy. Dokonce je možné zobrazit celou aktivitu jako plovoucí dialog. Nejprve se podíváme na vytváření jednoduchého potvrzovacího dialogu.

    Všechny dialogy by se měly vytvářet ve funkci onCreateDialog(). K vytvoření jednoduchého dialogu s jedním až třemi tlačítky lze využít třídu AlertDialog.Builder. Funkce onCreateDialog() s kódem pro vytvoření jednoduchého dialogu s dvěma tlačítky by potom vypadala takto:

    protected Dialog onCreateDialog(int id) {
         Dialog dialog;
         switch(id) {
         case DIALOG_YESNO:
             {
                 AlertDialog.Builder builder = new AlertDialog.Builder(this);
                 builder.setMessage("Přejete si ukončit aplikaci");
                 builder.setPositiveButton("Ano", new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int id) {
                         Hello.this.finish();
                     }
                 });
                 builder.setNegativeButton("Ne", new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int id) {
                         TextView tv = (TextView)findViewById(R.id.text);
                         tv.setText("Odpověď je ne");
                     }
                 });
                 dialog = builder.create();
             }            
             break;
         default:
             dialog = null;
         }
         return dialog;
    }
    

    Nejprve je nutné vytvořit instanci statické třídy AlertDialog.Builder. Pomocí ní se specifikuje, jak bude dialog vypadat. Nastavíme zobrazovanou zprávu a přidáme dvě tlačítka. Reakcí na stisk tlačítka “Ano” bude ukončení aktivity, reakcí na stisk tlačítka “Ne” bude nastavení textu pro TextView.

    Nyní zbývá vyřešit, jak systému sdělit, že chceme dialog vytvořit. Pro to stačí zavolat funkci showDialog(DIALOG_YESNO), kde DIALOG_YESNO je unikátní identifikátor tohoto dialogu.

    Dialog s vlastním vzhledem a funkcionalitou vytvoříme instanciováním třídy Dialog. V následujícím příkladu nejprve vytvoříme dialog. Druhý příkaz pak říká, že nechceme, aby dialog měl titulek. Dále mu nastavíme layout specifikující jeho vzhled. Nakonec přidáme akci vyvolanou při stisku tlačítka v dialogu – text v edit boxu v dialogu se zkopíruje do TextView v aktivitě a dialog se zavře pomocí funkce dismissDialog().

    case DIALOG_CUSTOM:
    {                        
            dialog = new Dialog(Hello.this, android.R.style.Theme_Dialog);
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setContentView(R.layout.my_dialog);
            final Dialog d = dialog;
            Button b = (Button)dialog.findViewById(R.id.btn_dialog_ok);
            b.setOnClickListener(new View.OnClickListener() {                        
                    @Override
                    public void onClick(View v) {
                            TextView tv = (TextView)findViewById(R.id.text);          
                            EditText et = (EditText)d.findViewById(R.id.edit_text);
                                       tv.setText(et.getText());
                            dismissDialog(DIALOG_CUSTOM);                                        
                    }
            });
    }        
    break;
    

    Layout pro dialog se tvoří stejně jako pro jakoukoliv aktivitu:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">
            <EditText
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:id="@+id/edit_text" />
            <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/btn_dialog_ok"
                    android:text="Nastavit" />
    </LinearLayout>
    

    Při práci s dialogy často využijeme funkci onPrepareDialog(), která nám dobře poslouží, pokud obsah dialogů není statický – chceme-li, aby zobrazoval nějakou měnící se informaci. V této funkci poté nastavíme aktuální obsah dialogu. Funkce onPrepareDialog() se volá vždy před zobrazením dialogu, naproti tomu onCreateDialog() se volá pouze před prvním vytvořením dialogu.

    Zmínil jsem se také o tom, že aktivitu je možné zobrazit jako plovoucí dialog. Taková aktivita se vytváří úplně stejně jako kterákoliv jiná, s jediným rozdílem – je třeba jí nastavit jiný styl. Konkrétně lze v manifestu nastavit aktivitě atribut android:theme="@android:style/Theme.Dialog". Aktivita se spouští pomocí intentu, nikoliv pomocí funkce showDialog() jako klasický dialog.

    Toast

    link

    Jiným užitečným konstruktem v systému je toast. Toast má sice k dialogu blízko, ale dialog to není. Je to malé view, které se vytvoří jako poloprůhledné plovoucí okno. Rozdíl oproti dialogům je, že toast nemá fokus a nelze na něm provádět akce. Pouze na určitou dobu zobrazí textovou zprávu. Elementy nacházející se pod ním jsou aktivní pro všechny uživatelské akce. Jeho vytvoření je jednoduché, stačí použít:

    Toast.makeText(this, R.string.my_msg, Toast.LENGTH_SHORT).show();
    

    První parametr je kontext, druhý zobrazovaná zpráva a třetí doba, po kterou bude zpráva zobrazena.

    AsyncTask

    link

    Nyní na chvíli opustíme dialogy a podíváme se na něco jiného. Generická abstraktní třída AsyncTask umí asynchonně spustit jiný kód. Užitečná je zejména v tom, že nemusíte ručně vytvářet nová vlákna a starat se o ně. Zároveň zajišťuje informativní nástroj pro zjištění stavu tasku. AsyncTask tak často využijeme při ošetření časově náročnějších operací. Například můžeme chtít, aby se během výpočtu zobrazoval dialog informující uživatele o prováděném výpočtu. K tomu lze použít například instanci třídy ProgressDialog. AsyncTask potom můžeme zavolat následovně:

    private void compute() {            
               AsyncTask<String,Void,Long> task = new AsyncTask<String, Void, Long>() {
                        private ProgressDialog mProgressDialog;                    
                            protected Long doInBackground(String... params) {
                               return Computation.computeSomething(params);
                            }        
                        protected void onPreExecute() {
                            mProgressDialog = ProgressDialog.show(Hello.this, "", "Počítám...", true);                            
                        }
                        protected void onPostExecute(Long result) {
                            mProgressDialog.dismiss();
                            TextView tv = (TextView)findViewById(R.id.text);
                            tv.setText("Výsledek je " + result);
                        }
               };
               task.execute(new String[]{"data1", "data2"});
    }
    

    Význam generických parametrů je po řadě – typ vstupních parametrů, typ updatového parametru a typ výsledku. V tomto kódu vytvoříme AsyncTask, který dostává jako parametry řetězce (String). V průběhu výpočtu neposílá žádnou informaci (Void) o svém pokroku a vrácená hodnota je typu Long.

    Funkce onPreExecute() se volá před započetím práce asynchronního tasku – zde vytváříme instanci progress dialogu, která informuje uživatele o probíhající činnosti. Ve funkci doInBackground() probíhá výpočet. A konečně ve funkci onPostExecute() se zpracovává vrácený výsledek – v tomto příkladě zobrazení výsledku v TextView. AsyncTask se spouští zavoláním funkce execute() s parametry.

    Pokud bychom nepoužili AsyncTask, ani vlastní řešení za pomocí vláken, aplikace by se z pohledu uživatele stala neresponzivní, čemuž je nutné se vždy vyhnout. Práce s asynchronními tasky vypadá snadně, je ovšem nutné dát si pozor na jejich použití ve vztahu k životnímu cyklu aktivit. Především je nutné si ohlídat, kde tasky skladujeme a inicializujeme, neboť změna konfigurace telefonu (způsobená například otočením displeje) defaultně resetuje aktivitu. To při špatném použití asynchronních tasků může vést k pádu aplikace.

    Závěr

    link

    Ukázali jsme si několik důležitých konstruktů, se kterými se programátor při vytváření aktivit často setká. Pověděli jsme si něco o listech a adaptérech. Ukázali jsme si, jak vytvářet dialogy a toasty. A nakonec jsme zmínili i AsyncTask, který nám dokáže ušetřit spoustu práce s vlákny.

    Inmite

    Chceš se naplno pustit do vývoje skvělých aplikací pro Android? Pošli nám CV na chci.job@inmite.eu – v Inmite právě hledáme posily do našeho androidího týmu! Pokud nás chceš napřed poznat a nezávazně pokecat, určite se ukaž na Android Devcampu, na jehož organizaci se podílíme. Inmite je už od samého začátku českou jedničkou ve vývoji pro Android a s tvou pomocí bychom si pozici rádi upevnili :)

           

    Hodnocení: 100 %

            špatné • dobré        

    Nástroje: Tisk bez diskuse

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    Komentáře

    Vložit další komentář

    5.5.2011 08:32 Honza
    Rozbalit Rozbalit vše Re: Vývoj pro Android – vylepšujeme aktivity
    AsyncTask pouzivam velice casto a k nemu se vaze muj dotaz. V metode postExecute potrebuji zobrazit dialog se zpravou o probehle akci. Vse funguje samozrejme v poradku, pokud uzivatel zustane v te same aktivite, ve ktere byl AsyncTask spusten, protoze do konstruktoru AsyncTasku posilam referenci na tu Activitu. Pokud ale uzivatel prejde do jine activity (coz je vice nez pravdepodobne), pak context aktivity uz neni platny a aplikace spadne. Proto misto dialogu pouzivam Toast, nebo popripade vypisuji zpravy do Notifikacniho pruhu. Poradil by mi nekdo, jak docilit toho, aby zobrazeni Dialogu nezpusobilo pad aplikace a aby se dialog pokud mozno zobrazil i na plose (pokud uzivatel opusti uplne aplikaci)?
    5.5.2011 08:37 Honza
    Rozbalit Rozbalit vše Re: Vývoj pro Android – vylepšujeme aktivity
    mam samozrejme na mysli onPostExecute()
    tmr avatar 5.5.2011 22:24 tmr | skóre: 17 | blog: Offtopic | Praha 5
    Rozbalit Rozbalit vše Re: Vývoj pro Android – vylepšujeme aktivity

    Tohle je jedna z věcí, kterou má Android naprosto špatně navrženou. Neexistuje žádný standardní postup, jak řešit čistě a bez bugu provádění kódu na pozadí s následným updatem UI. Problémy s AsyncTaskem jsou 2:

    1. AsyncTask má odkaz na Activity. Při otočení telefonu na šířku se Activity restartuje, ale AsyncTask má odkaz na tu starou Activity. Takže v paměti jsou 2 a jedna z nich zbytečně. Když AsyncTask skončí a chce zobrazit výsledek, nefunguje to, protože nemá odkaz na novou Activity.
    2. Dejme tomu, že mám Activity, která zabírá hodně paměti a v onCreate() spustí AsyncTask. Když několikrát převrátím telefon, Activity se několikrát restaruje a vytvoří několik AsyncTasku. Kazdy bude mít odkaz na tu svou Activity, takže se postupně zaplní paměť a skončí to OutOfMemoryError-em.

    Oba problémy se zdaleka netýkají jenom otáčení displeje, to je jenom nejčastější případ.

    Já jsem AsyncTasky přestal používat a pro práci na pozadí používám vlastní třídy Task (obdoba AsyncTask) a AbstractActivity (například udržuje informace o běžících Tascich).

    8.11.2011 16:00 Mira
    Rozbalit Rozbalit vše Re: Vývoj pro Android – vylepšujeme aktivity
    Nenastinil by jsi prosim jak tebou zminovany problem resis, pomoci te sve vlastni tridy?

    Moc dik
    6.5.2011 02:05 Tomáš Kypta
    Rozbalit Rozbalit vše Re: Vývoj pro Android – vylepšujeme aktivity
    Pokud chcete dialog, který není vázán na konkrétní aktivitu nebo se umí zobrazit na ploše, budete ho muset vytvořit z vlastní aktivity. Tu zobrazíte s dialogovým stylem.
    8.5.2011 20:22 Jakub
    Rozbalit Rozbalit vše Vlakna jejich stavy
    Zdravim,

    mam banalni dotaz ale ani v dokumentaci jsem nenasel odpoved.

    Je mozne mit v Androidi aplikaci vlakno(extend Thread) a provadet na nem nasledujici 3 veci?
    1. Pozastavit
    2. Spustit(nechat ho pokracovat z pozastaveneho mista)
    3. Dotazat se zda je bezici, pozastavene nebo mrtve?
    Diky moc Kuba.
    tmr avatar 8.5.2011 23:43 tmr | skóre: 17 | blog: Offtopic | Praha 5
    Rozbalit Rozbalit vše Re: Vlakna jejich stavy

    Nejde to. Muzes ale tomu threadu rict, ze chces aby se pozastavil. A v tom threadu budes cas od casu kontrolovat, jestli je pozadavek na pozastaveni, a kdyz je tak se zastavis. Z jineho threadu potom muzes ten thread zase probudit.

    P.S. Na co to potrebujes?

    10.5.2011 10:09 Jakub
    Rozbalit Rozbalit vše Re: Vlakna jejich stavy
    Ahoj,

    diky za odpoved - kterou jsem nechtel slyset.

    Mam tridu ktera mi spravuje tasky(nacitani obrazku po siti). Porad dokola kontroluje jestli nepribyl novy task, pokud task pribyl zkontroluje jestli je volno(jiny jeste nebezi) a pokud je, tak ho spusti.

    Zpusob jak to resit je, pres zamky. Do toho se mi ale moc nechce :(.

    Je primo v androidovi nejaka komponenta o ktere nevim a pomohla by mi?

    Diky za pomoc.

    Založit nové vlákno • Nahoru

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.