• úvod
  • témata
  • události
  • tržiště
  • diskuze
  • nástěnka
  • přihlásit
    registrace
    ztracené heslo?
    LWEEKAndroid development
    Diskuse o vývoji aplikací pro platformu Android.
    -----------------
    Tipy, Triky, Postřehy, Začátečnický help, Nápady na nové aplikace.

    Oficiální developerská stránka: http://developer.android.com
    Něco málo v češtině na WiKi android fora: http://wiki.androidforum.cz/index.php/Programov%C3%A1n%C3%AD
    Článek na Zrojáku: http://zdrojak.root.cz/clanky/vyvoj-pro-android-ii/

    Docela zajímavé tutoriály přímo od vývojářů ze Sony Ericsson:

    na tvorbu vlastního View adapteru
    http://blogs.sonyericsson.com/developerworld/2010/05/20/android-tutorial-making-your-own-3d-list-part-1/

    zajímavý nápad na zoomování jedním prstem - aneb vytváření gest
    http://blogs.sonyericsson.com/developerworld/2010/05/18/android-one-finger-zoom-tutorial-part-1/
    rozbalit záhlaví
    VIRTUALVOID
    VIRTUALVOID --- ---
    DATEL: skus obe, uvidis co ti bude vyhovovat viac :)
    DATEL
    DATEL --- ---
    DRIZDIK: hm, zajímavé, takže každý fragment máš v podstatě samostatný "blackbox", který funguje kompletně sám o sobě včetně načítání a ukládání dat? Zatím jsem právě všude viděl (knihy, tutoriály i android dokumentace) to, že se má ve fragmentu vytvořit interface, který aktivita musí implementovat a tyhle ukládací věci se pak dělají v aktivitě. Na druhou stranu tvé řešení má výhodu, že fragment je opravdu samostatná jednotka, kterou když přesunu do jiné aktivity, tak by měla víceméně fungovat, aniž bych musel přenášet i metody z jedné aktivity do druhé.

    No, tak teď fakt nevím, kterou cestou se dát :)
    DRIZDIK
    DRIZDIK --- ---
    DATEL:
    já tohle řeším tak, že tyhle data (nejlépe pouze id) předám fragmentu v Argumets bundlu. Fragment se poté sám postará o zobrazení progress, načtení na pozadí vlastním loaderem a zbrazení případně uložení. Snažím se ho jako funkční celek oddělit od aktivity, aby byl použitelnej i na jíném místě.
    Mezi fragmenty komunikuju pomocí Observer patternu a funguje to relativně dobře.

    Rozdělení na je celkem na tobě. Někdo se snaží vše řešit v jednom, někdo odděluje, aby se zachovávali intenty, které ti pak pomůžou pži zabití aktivity obnovit předchozí stav - to je velice důležitý.
    DATEL
    DATEL --- ---
    VIRTUALVOID: super, tohle je mi už jasný, díky :)
    VIRTUALVOID
    VIRTUALVOID --- ---
    DATEL: co zoznam, to aktivita. urob niekde menu/zoznam, ake veci vlastne chces urobit. potom si sprav mockupy...

    alebo inak to skusim napisat: co typ entity to samostatna aktivita+fragmenty
    DATEL
    DATEL --- ---
    VIRTUALVOID: VIRTUALVOID: Ok, tomu rozumím, ale pokud ta aplikace bude mít více různých seznamů, formulářu apod., tak v té hlavní aktivitě by ty akce mohly narůst velice rychle a ten počet 40 překročit. Ono už vlastně i to, že aktivita implementuje události fragmentů např. pro uložení dat po odeslání formuláře, naplňování formulářů z daty atd., způsobí její nabobtnání. Nebo co by vlastně samotný fragment měl všechno řešit? Pouze obsluhu svých View (eventuelně otevírání dalších aktivit/dialogů, např. pro výber datumu)? Veškeré ukládání dat pak předává právě aktivitě.
    VIRTUALVOID
    VIRTUALVOID --- ---
    hlavna aktivita by potom mala riesit cez callbacky operacie daneho fragmentu
    VIRTUALVOID
    VIRTUALVOID --- ---
    DATEL:
    Na jednu stranu pokud je mám všechny v jedné aktivitě, tak bude jednodušší komunikace mezi fragmenty, na druhou stranu, kdyby byla aplikace rozsáhlejší, tak mít všechno v jedné aktivitě je podle mě taky nesmysl.

    nieje to nezmysel. pretoze by si nikdy nemal mat 40 akcii v jednej aktivite, ale nejak logicky to rozdelovat.

    ja som doteraz vzdy siel cestou hlavna aktivita + jej logicky patriace fragmenty.
    v tomto pripade :
    hlavna aktivita :
    - fragment pre zobrazenie v liste
    - fragment pre editaciu/zobrazenie detailu

    na editaciu / detail nepotrebujes dva rozne fragmenty... len ked dany zaznam budes otvarat ako detail tak nastavis textboxy,etc. ako readonly. napr.
    DATEL
    DATEL --- ---
    VIRTUALVOID: díky za tip, jsem začátečník, takže parcelable neznám (respektive zahlédl jsem ho v dokumentaci), tak se na to podívám - předpokládám, že to umožňuje dávat do intentu jakýkoliv objekt, takže půjde nejspíš o implementaci nějakého rozhraní, pomocí kterého se v té třídě Record určí, co se ukládá atd.?

    A jak s těmi fragmenty? Blbý je, že ať kouknu kam chci, tak všechny tutoriály i EN knihy fragmenty nakousnou jen v základu a jako příklad tam dají seznam a vložení nové položky, ale třeba právě editaci již existující a právě přenos dat do fragmentu (eventuelně skrz další aktivitu) se nikde neřeší :(
    VIRTUALVOID
    VIRTUALVOID --- ---
    DATEL: sprav to ako parcelable, nech nemusis puttovat do bundlu objekty na per property basis
    DATEL
    DATEL --- ---
    A teď bych měl dotaz z jiného soudku. Základy jsem studoval ze seriálu na Zdrojáku. Rád bych se zeptal, jakým způsobem řešíte fragmenty ve spojitosti s activity.

    V tom tutoriálu (http://www.zdrojak.cz/clanky/vyvijime-pro-android-fragmenty-a-sqlite-databaze/) je totiž pro variantu "malé" obrazovky použita sólo aktivita pro fragment s formulářem a sólo aktivita pro zobrazení detailu (a samozřejmně hlavní aktivita). Oproti tomu v dokumentaci (http://developer.android.com/training/basics/fragments/communicating.html) používají pouze jednu hlavní aktivitu pro všechny fragmenty.

    Kdybych nepoužil fragmenty, tak je jasné, že pro každou zmíněnou akci budou sólo aktivity. Jakým způsobem je tedy lepší fragmenty začleňovat do aktivity? Na jednu stranu pokud je mám všechny v jedné aktivitě, tak bude jednodušší komunikace mezi fragmenty, na druhou stranu, kdyby byla aplikace rozsáhlejší, tak mít všechno v jedné aktivitě je podle mě taky nesmysl.

    Dá se tedy říci, že pro malé aplikace se dá použití varianta jedné aktivity pro všechny fragmenty a pro větší aplikace (co je větší aplikace?) pak rozdělení na více aktivit?

    Právě řeším v té jednoduché aplikaci to, že fragmenty mám ve více aktivitách a potřebuju při výběru položky ze seznamu (hlavní aktivita) otevřít formulář a naplnit ho daty z DB - což je až ve fragmentu, ale v jiné aktivitě. Takže pokud aktivita pro zobrazení fragmentu s formulářem vypadá takto:
    public class AddRecordActivity extends FragmentActivity implements
        AddRecordFragment.OnAddRecordListener {
        
        public static final String EXTRA_DATE = "date";
        public static final String EXTRA_DAILY_COUNTER = "dailyCounter";
        public static final String EXTRA_MAIN_COUNTER = "mainCounter";
        public static final String EXTRA_DESCRIPTION = "description";
        
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.add_record_container);
        }
    
        @Override
        public void onAddRecord(Record record) {
            Intent result = new Intent();
            result.putExtra(EXTRA_DATE, record.dateInMillis);
            result.putExtra(EXTRA_DAILY_COUNTER, record.dailyCounter);
            result.putExtra(EXTRA_MAIN_COUNTER, record.mainCounter);
            result.putExtra(EXTRA_DESCRIPTION, record.description);
    
            setResult(RESULT_OK, result);
            finish();
        }
        
    }
    

    a v hlavní aktivitě se tato aktivita otevírá takto:
                Intent i = new Intent(this, AddRecordActivity.class);
                i.putExtra(AddRecordActivity.EXTRA_DATE, record.dateInMillis);
                i.putExtra(AddRecordActivity.EXTRA_DAILY_COUNTER, record.dailyCounter);
                i.putExtra(AddRecordActivity.EXTRA_MAIN_COUNTER, record.mainCounter);
                i.putExtra(AddRecordActivity.EXTRA_DESCRIPTION, record.description);
                startActivityForResult(i, REQUEST_UPDATE_RECORD);
    

    tak tam budu muset dělat dalšího prostředníka pro přenesení dat do fragmentu.
    DATEL
    DATEL --- ---
    DRIZDIK: breaknout myslíš hodít si breakpointy pro debugger? No, ona ta výjimka je jen občas, zkouším otevírat dialogy, zavírat je atd. a vyskytne se to jen občas. Hlásí, že se finalizuje kurzor, který nebyl deaktivován nebo uzavřen. Problém je, že se to vyvolá jen někdy. Dle jedné situace jsem myslel, že se při otevření nové aktivity s tím fragmentem a formulářem nevyvolají onPause atd. pro fragment se seznamem a pak, když uložím novou položku, tak se vyvolá update seznamu, kde se vytváří znova kurzor a tom to vyhodí tu výjimku. Jenže už se mi i stalo, že mi to tu samou výjimku do LogCatu vyhodilo i ve chvíli, kdy jsem měl otevřený ten formulář pro novou položku a z něj otevřel ještě dialog pro výběr datumu - tady teda moc nechápu, proč se obnovoval seznam. Blbý je, že to je všechno náhodně, nedá se to přesně replikovat, takže nějaké ladění v debuggeru asi mi moc nepomůže :(
    GORG
    GORG --- ---
    DRIZDIK: Všiml jsem si, že se tam nějaký thread pool zřejmě vytváří... v DDMS jsem viděl právě hromadu těch vznikajících thread-pool- workerů. Nevím, jestli já to přímo můžu omezit, ale ten zmíněný Continuation zřejmě thread pool používá.
    DRIZDIK: Nezkoušel.. zkusím se na to příště zaměřit. Na konci to byl OutOfMemory exception, ale možná tam bylo předtím víc informací.
    GORG
    GORG --- ---
    REDGUY: Ja tam přímo ty thready nevytvářím. To dělá třetí strana formou classy Continuation, což je handler, co mi má volat po dokoneční jejich asynchronní operace. Já tedy přímo v tomhle případě ty thready nevytvářím. Všiml jsem si, že když to zahltím požadavky, dokáže se dostat do stavu, kdy přibývají nové thready cca 50 nových vláken za sekundu, dokonce aniž by přibývaly další požadavky (na další stahování). Zdálo se mi, že to souvisí s nějakým deadlockem na přistup k vnějším proměnným. To se mi, zdá se, podařilo skoro vyřešit, i když mi není přímo jasné, čím přesně mi to podařilo.

    situace se má konkrétně nějak takto:



    rssFeedController.requestAllItems(new Continuation<List<RSSItem>>() {



    @Override

    public void withValue(List<RSSItem> arg0, Exception arg1) {

    // tady je zpracování dat získaných v arg0

    // jejich vynášení ven mimo tuto funkci delalo ty problémy



    }
    DRIZDIK
    DRIZDIK --- ---
    DATEL: Zkoušel jsi breaknout kdy ti to umře? Asi se ti volá saveFragmentViewState až po tom co kurzor zavřeš. Jenže pokud ho neodstraníš z toho adaptéru, tak ten se ještě snaží uložit pozici v listu atd ..
    DRIZDIK
    DRIZDIK --- ---
    GORG: Na tohle určitě používat ThreadPool a ThreadPoolExecutor s nastaveným jedním threadem, nebo prostě minimum, aby se brzy objevili takovéhle problémy tím, že se ti začne ucpávat ta fronta. Docházející paměť se špatně hledá ..
    REDGUY
    REDGUY --- ---
    GORG: Chapu spravne ze delas extra thread pro kazdej request, kterejch potencialne muze bejt moc? Nebylo by lepsi mit par pevnejch worker threadu, ktery by brali praci z nejaky fronty? Pokud je pouzivas ke stahovani dat po siti, tak stejne hadam ze bottleneck je ta sit a hodne threadu soucasne bud nepomuze, nebo dokonce uskodi...
    GORG
    GORG --- ---
    Nakonec jsem totiž zjistil, že rychlost (FPS) občas zadrhávalo (jak jsem tu před časem psal) právě tohle leakování threadů.
    GORG
    GORG --- ---
    Nevím, jestli je to dotaz vhodnější na Javu nebo Android, ale narazil jsem na problém při asynchronních požadavcích, kdy se mi hromadí (leakuje) work pool Thready - replikovatelné zejména, pokud z daného threadu chci získat (přeposlat ven) nějakou hodnotu do hlavního threadu. Jde o stahování souborů z internetu na pozadí. Když se to při testování snažím zahltit požadavky, tak se pak thready začnou hromadit po desítkách za sekundu než dojde nakonec paměť.
    Nejsem moc zatím zběhlý ve vícethreadových aplikacích, takže si ani nejsem jistý, jestli záležitosti synchronizace threadů řeším správně.
    Jinak stručně mi jde o to stáhnout na pozadí nějaký soubor, aby se tím aplikace nezadrhávala. Nejde mi vůbec o čas, jen aby to nedělalo problémy.
    DATEL
    DATEL --- ---
    A ještě bych měl dotaz k fragmentům a aktivitám co se týče reakce na události.

    Mám situaci, kdy hlavní aktivita obsahuje tlačítko pro přidání záznam a pak fragment se seznamem položek. Obsluha přidání nového záznamu je jasně v oné hlavní aktivitě, kde se zavolá intent a startActivityForResult pro otevření druhé aktivity, která pak obsahuje fragment s formulářem.

    Ve fragmentu se seznamem položek se pak dá nad položkou vyvolat kontextové menu, kde je možnost položku smazat nebo upravit. A teď, tento fragment přímo obsluhuje událost kliknutí na menu položku pro smazání, tj. smaže položku a obnoví seznam. Jak bych měl ale správně implementovat vyvolání úpravy položky? Formulár pro přidání je vyvolán z aktivity. Měl bych tedy z fragmentu pouze vyvolat nějakou událost, na kterou bude mít ta aktivity navěšený listener a tedy dialog pro úpravu opět otevře aktivita? Nebo by ten formulář pro úpravu měla vyvolat přímo ta aktivita seznamu?
    DATEL
    DATEL --- ---
    Hm, tak mi zase vyběhla výjimka s kurzorem, já se na to už fakt vytento :( Tentokrát když jsem dal tlačítko Back nebo submit v aktivitě s fragmentem s formulářem pro přidání položky. Tak nevím, máte někdo zkušenosti s tím novým LoadManagerem? Ten by tu správu kurzorů atd. měl řešit sám, ale co jsem zatím tak koukal, tak z toho moc moudrý nejsem.
    Kliknutím sem můžete změnit nastavení reklam