2012-05-21

Problem med View Swiping och orientation changes


Jag har byggt en app med View Swiping enligt den här artikeln. Jag har gjort några ändringar för att det ska passa min app.

Min implementation:
En FragmentActivity som har en ViewPager.
ViewPager har en FragmentPagerAdapter.
I FragmentPagerAdapter så skapas det upp 6 stycken ListFragment.
Varje ListFragment har en ArrayAdapter som ska hålla sina Items.
Jag lägger till Items till varje adapter beroende på vilken status ett item har med:
fragmentPagerAdapter.getItem(listIndex).getAdapter ().add(item);
Det fungerar galant första gången jag visar mina listfragment.

Problemet:
När jag vrider på telefonen så skapas allt om via onDestroy() och onCreate() som det ska, men mina listfragment blir tomma. Jag har skapat om dem så det borde bli samma sak som första gången jag laddar allt.
Felet beror på att Android återanvänder listfragmenten som skapades första gången och de är inte samma som jag lägger till mina items till. Därför blir listorna tomma.
Jag använder getItem() för att få tag i mitt listfragment, men det gör inte Android. Den anropar inte ens getItem() andra gången utan letar reda på dem via instantiateItem().

Min lösning:
Lösningen känns lite som ett hack, men fungerar väldigt bra (det skapas dock upp några extra fragment, men det är nog inte jätteofta som användarna kommer att vrida telefonen fram och tillbaks just i listvyn där det här används):
Gör en override på: public Object instantiateItem(ViewGroup container, int position) i FragmentPagerAdapter:
Kod:
@Override
public Object instantiateItem(ViewGroup container, int position) {
ItemsFragment fragment = (ItemsFragment) super.instantiateItem(container, position);
if(fragment.getAdapter() == null) {
ItemsFragment myFragment = getItem(position);
fragment.setListAdapter(myFragment.getAdapter());
fragment.setTitle(myFragment.getTitle());
}
return fragment;
}
Notera: Mitt ItemsFragment har en ny metod getAdapter() som returnerar en typad adapter "ItemListAdapter" och nya metoder för set och getTitle() som används för att få rätt texter på PagerTitleStrip i ViewPagern.

Jag använder min metod getAdapter() för att kolla om det funna fragmentet har en adapter. Om den inte har det så tar jag en adapter via metoden getItem() som returnerar fragments som jag har kontroll på.

Ni kanske undrar varför jag helt enkelt inte bara lägger till:
android:configChanges= "orientation|keyboardHidden|screenSize"
i manifestet. För det första så ska den tekniken undvikas eftersom det gör hanteringen av resources onödigt komplicerad. Vidare så hanteras inte ActionBar och PagerTitleStrip korrekt.

Nästa steg nu är att använda:
onRetainCustomNonConfigurationInstance/getLastCustomNonConfigurationInstance
för att slippa ladda om all data mellan vridningarna av telefonen.

Ref: Mitt inlägg på Swedroid