Jak zabít několik much jednou ranou přechodem na fragmenty
1. Jak zabít několik much
jednou ranou přechodem
na Fragmenty
+David Vávra pro GUG ČVUT
2. Dlužníček
● Společné výdaje, 50k+ stažení
● mouchy:
○ na tabletech roztažené
○ není úplně podle Android
Design guidelines
■ dashboard screen
■ Nová platba a Kdo má
platit jsou akce
○ Swipe mezi skupinami
○ rotace obrazovky => android:
configChanges="orientation"
○ jinak AsyncTasky leaknou
aktivitu
○ nepoužívají se observery na
data
○ View not attached to window
manager Exception
○ mohlo by být rychlejší
3. Co s tím? Fragmenty!
● nové API Android 3.0 Honeycomb (+ Compatibility Library)
● znovupoužitelné UI komponenty
● http://developer.android.com/guide/components/fragments.html
10. Zásek #1: řešení
● Jedna aktivita
○ hacky ActionBaru
○ rotace, rotace, rotace a zachování stavu
○ tlačítko back
■ addToBackStack - buggy = Fragmenty přes sebe
■ ale pak nejde použít setRetainInstance(true) => problémy s
AsyncTasky a savedIntanceState
● Dvě aktivity
○ ActionBar definovaný v aktivitě handling ve fragmentu
○ je jasné co bude po rotaci = stejná aktivita
○ back funguje out of the box
○ setRetainInstance(true) funguje krásně
○ bez hacků
○ animaci mezi aktivitami jde vypnout
11. Zásek #2: AsyncTasky a
observery
public class SettleUpFragment extends SherlockFragment protected void registerObserver(Uri uri) {
{ this.uriToObserve = uri;
protected SettleUpActivity c; // TODO: multiple observers
private Uri uriToObserve = null; c.getContentResolver().registerContentObserver(uri,
private AsyncTask<Void, Void, Void> true, observer);
fillDataTask; }
private NewAsyncTaskCallback
newAsyncTaskCallback; protected void loadData(NewAsyncTaskCallback
@Override callback) {
public void onAttach(Activity activity) { this.newAsyncTaskCallback = callback;
super.onAttach(activity); this.fillDataTask = callback.
c = (SettleUpActivity) activity; onCreateAsyncTask();
} fillDataTask.execute();
@Override }
public void onDetach() {
super.onDetach(); ContentObserver observer = new ContentObserver
if (fillDataTask != null) { (null) {
fillDataTask.cancel(true); @Override
} public void onChange(boolean selfChange) {
} if (fillDataTask != null && !
@Override fillDataTask.isCancelled()) {
public void onDestroyView() { SettleUpFragment.this.fillDataTask
if (uriToObserve != null) { c. = newAsyncTaskCallback.onCreateAsyncTask();
getContentResolver().unregisterContentObserver fillDataTask.execute();
(observer); }
} }
if (fillDataTask != null) { };
fillDataTask.cancel(true);
} public interface NewAsyncTaskCallback {
super.onDestroyView(); AsyncTask<Void, Void, Void>
} onCreateAsyncTask();
}
}
12. Zásek #3: ViewPager & taby
● aplikace nepočítala s více skupinami
● invalidace ViewPageru:
○ uiViewPagerIndicator.invalidate()
○ při změně tabu:
uiViewPager.getAdapter().
notifyDataSetChanged();
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
● handling ActionBaru z aktuálního
ViewPager fragmentu:
SettleUpFragment fragment = (SettleUpFragment)
uiViewPager.getAdapter().instantiateItem
(uiViewPager, uiViewPager.
getCurrentItem());
if (fragment != null) {
return fragment.
onOptionsItemSelected(item);
}
13. Zásek #4:
PreferenceFragment
● Není v Compatibility library
● Tutoriál: http://developer.android.com/guide/topics/ui/settings.html#BackCompatHeaders
○ Android >3.0 preference-headers
○ Android <3.0 PreferenceScreen s Intenty
● Co když je potřeba přidat listenery atd?
○ samostatná třída co je inicializovaná z Activity nebo Fragmentu
14. Shrnutí
● Zabité mouchy:
○ na tabletech vypadá dobře
○ podle Android Design Guidelines
○ rotace obrazovky, pamatování stavu + AsyncTasky bez problémů
○ aplikace svižnější
○ donutilo mě to k používání observerů a ORM
○ víc zapouzdřených komponent = v Aktivitě minimum kódu
● Ale:
○ velký refaktoring celé aplikace
○ záseky kde i StackOverflow drhne (snad jich po dnešku bude míň)
● Takže:
○ pro nové aplikace určitě, pro existující zvážit
○ šance jak se prosadit v davu aplikací - HoloEverywhere.com atd.
■ Aplikace Tasks - za 3 měsíce 100k stažení placené verze