2012-05-22 21 views
8

Potrzebuję rozwiązania do implementacji pagera widoku. Po pierwsze ładuję ogromne dane z bazy danych na jednej stronie, więc czasami podczas machnięcia spowalnia częstotliwość machnięcia (trzeba przesunąć wiele razy na stronie), jak w tle robi zadanie pobierania. Nie używam zadania async do zwracania widoku. Czy istnieje sposób na leniwy załadować strony po prostu pozwól użytkownikowi przejść na inną stronę po przesunięciu, ale dane są leniwy załadowany.Dane obciążenia Android asynchronicznie w widoku pagera

Moja próbka kodu wygląda następująco;

public Object instantiateItem(View container, int position) { 

View v; 

v = View.inflate(context,R.layout.swipearea, null); 

listView = (ListView)v.findViewById(R.id.MyListView); 
largeDataCall(); 
((ViewPager)container).addView(v); 
return v; 
} 

Wezwę to do metody tworzenia.

pager=(ViewPager) findViewById(R.id.pagerAdapter); 
pager.setAdapter(new SimplePager(MyPager.this)); 
pager.setCurrentItem(364); 

Czy istnieje rozwiązanie?

Odpowiedz

0

Nie sądzę, że istnieje sposób na leniwą ładowanie danych w sposób synchroniczny, który opisujesz. AsyncTask jest do zrobienia, a może możesz użyć wątków bezpośrednio. Uważam, że AsyncTask został zaprojektowany specjalnie dla tego rodzaju funkcjonalności. Łatwiej jest użyć tego wątku bezpośrednio. Jeśli potrzebujesz pomysłów dotyczących implementacji, spójrz na: http://geekjamboree.wordpress.com/2011/11/22/asynctask-call-web-services-in-android/

+1

Nie widzę żadnej implementacji pagera widoku w podanym łączu. – Hanry

+0

Przykładowy pager widoku można zobaczyć: http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html i http://android-developers.blogspot.in/2011/08/horizontal -view-swiping-with-viewpager.html. Tę implementację należy zaimplementować za pomocą AsyncTask, aby uzyskać optymalny komfort użytkowania. –

17

Proponuję pracować z Fragmentami (a nie bezpośrednio z widokami).

Potrzebny jest interfejs w swoich fragmentów im powiedzieć, kiedy są pokazane:

public interface IShowedFragment { 

    public void onShowedFragment(); 
} 

Dodać wszystkie fragmenty wdrożenia tego interfejsu, w tym metody zadzwonić do ładowarki/asyncTasks/zadania w tle.

Następnie umieść onPageChangeListener w ViewPager, a gdy wykryjesz, że użytkownik zmienił stronę, wywołaj metodę interfejsu na swoim fragmencie. Masz kilka opcji z tym słuchaczem, jedną z metod możesz czekać, aż viewPager przestanie się przesuwać, aby wywołać twoje połączenie z interfejsem.

Aby uzyskać odpowiedni fragment do wykonania tego połączenia, weź fragment z pliku FragmentApadter.instantiateItem (ViewGroup, int), który zwróci fragment dla tej pozycji, jeśli jest już załadowany.

mPager.setOnPageChangeListener(new OnPageChangeListener() { 

    @Override 
    public void onPageSelected(int position) { 

     Fragment fragment = (Fragment) mAdapter.instantiateItem(mPager, position); 
     if(fragment instanceof IShowedFragment){ 
      ((IShowedFragment) fragment).onShowedFragment(); 
     } 
    } 
    (...) 

W ten sposób możesz przygotować fragmenty z pustymi widokami, a po zsunięciu na nie zaczniesz ładować dane.

+0

Czy masz jakieś przykładowe wdrożenie? – Hanry

+3

Fragmenty ułatwiłyby Ci życie. Jeśli zaimplementowałeś je w fragmencie, możesz ładować dane (asynchronicznie) w dowolnym momencie, a następnie wyświetlać je w createView() Fragmentu. http://developer.android.com/reference/android/support/v13/app/FragmentStatePagerAdapter.html – DeeV

+1

Dodano implementację (brakuje tylko fragmentu przykładu, w którym zostałaby zaimplementowana funkcja onShowedFragment() i ładowanie danych asynchronicznie) . – galex

1

instantiateItem jest wywoływana, gdy ViewPager ma zamiar zamienić i potrzebuje widoku. To nie ma potrzeby, aby faktycznie tworzyć wszystko. Myślę, że ostatecznie, leniwe ładowanie się skończyło. Tak jak to widzę, są dwie rzeczy, które musisz tutaj zrobić.

1: Cache dane w tle, gdy użytkownik zbliża się do Twojej strony. Twój przykład twierdzi, że 364 strony (dobry Lord), więc powiedziałbym, że użyję detektora do obsługi zmian strony. Kiedy jesteś na stronie 363, zacznij ładować dane dla 364. Kiedy jesteś w 364, zacznij ładować dane w 365 i utrzymuj dane na 363 na wypadek, gdyby użytkownik chciał zamienić. Jeśli dane wczytują się stosunkowo szybko lub użytkownik potrzebuje długiego czasu na zamianę, powinno to być bezbłędne, zakładając, że używasz asyncTask lub wątku do załadowania danych.

2: mieć domyślny widok zapasowy, który nie zostanie wypełniony, dopóki dane nie zostaną odzyskane. Musisz to zrobić również z opcją 1 na wypadek, gdyby użytkownik wczytał stronę przed pobraniem danych.Zasadniczo, po prostu mieć widok, który mówi "ładowanie ..." lub coś, dopóki nie masz danych. Albo to albo zapełnij dane w czasie rzeczywistym, kiedy je otrzymasz. W takim przypadku użytkownik zobaczy, jak jest tworzony.

Tak czy inaczej, myślę, że będziesz musiał cache'ować coś, aby aplikacja wyglądała dobrze.

+0

W logu widzę, że pager widoku rozpoczyna ładowanie danych za 363,364,365 jednocześnie, gdy ustawiam bieżący element na 364.więc nie ma problemu z pierwszym ładowaniem, ale jako przeciągnięcie użytkownika, powiedzmy od 364 do 365, viewpager zaczyna ładować dane dla strony 366, ale jeśli dane na stronie 366 są bardzo wysokie, to widzę, że widok zamarza na kilka sekund. – Hanry

+0

To oznacza, że ​​ładujesz dane synchronicznie dla trzech różnych stron w wątku UI, z których dwa nie są widoczne. Również połowa twojej pracy została wykonana. Użyj wątku i powinno to znacznie przyspieszyć. – DeeV

+0

Nadal potrzebujesz domyślnego widoku "jeszcze nie zrobione", jeśli nie pobierzesz wszystkich danych, gdy użytkownik przeciągnie. – DeeV

0

Czy przejrzałeś android ignition library? zgodnie z Sample-applications jest składnik "Lista nieskończona" i składnik pamięci podręcznej http.

I miałaś spróbowałem sobie i nie wiem czy jest to rozwiązanie dla ciebie-tylko zobaczył przykłady .....

3

Właśnie zakończył bardzo podobne zadanie. Aby zacząć od znalezienia rozwiązania swojego problemu, rozważ następujące punkty w kolejności;

  1. Spójrz, czy trzeba być pobieranie wszystko tych danych w pierwszej instancji. Możesz wysłać z powrotem szczegółowe informacje o tym, jakie informacje chcesz załadować i co z nimi robisz (wyświetlając je jako listę na ekranie?).
  2. Sprawdź, czy używasz CursorLoader s wykonujących zadania o dużym udźwigu jako baza danych pobiera asynchronicznie. This tutorial w interwebs wprowadza podejście ContentProvider Android. Najlepiej zapoznać się z oficjalnym dokumentem URI Androida i dokumentacją ContentProvider, jeśli te warunki nie mają większego znaczenia.
  3. Jeśli pracujesz z Fragmentami - spójrz na użycie FragmentStatePagerAdapter zamiast tradycyjnego FragmentPagerAdapter. Nie użyłem tego adaptera, ale przeczytałem, że tworzy on tylko obecnie widoczny Fragment, tzn. Nie fragmenty po prawej lub lewej stronie aktualnie wybranej karty.
  4. Sprawdź optymalizację kwerendy, której używasz do bazy danych.
+0

Zgadzam się z DeeV. Zadanie to stanie się łatwiejsze (i bardziej standardowe), jeśli Fragments zostały użyte dla każdej strony ViewPager. Kiedy Fragment ma być wyświetlany, zostanie wywołany onCreateView, gdzie możesz zainicjować swoje '' '' CursorLoader''''s etc dla async db access i seemless UI. Jest to oczywiście możliwe wbrew powyższym komentarzom, ponieważ wielu, wielu innych to zrobiło. – OceanLife

1

Miałem podobny problem. Viewpager, który ładował ciężkie dane. Jeśli nie zamierzasz często zmieniać widoków poszczególnych stron, sugerowałbym, aby zachować strony w pamięci. Użyj następującego kodu, aby wykonać tę

mViewPager.setOffscreenPageLimit(#pages); to keep #pages in memory. I had 5 pages so my #pages was 4. 

Jeśli chcesz odświeżyć dane na slajdach viewpager użyć

mViewPager.getAdapter().notifyDataSetChanged(); with getItemPosition() returning POSITION_NONE. 

I używać FragmentStatePagerAdapter.

Powiązane problemy