5

Mam konfigurację ViewPager, która pobiera dane dla swoich stron (widoków) z danych przekazywanych z serwera. Czasami serwer wysyła nowe dane, które zmieniają kolejność wyświetleń (a czasami dodają nowe widoki) i muszę sprawić, że stanie się to bezproblemowo na moim urządzeniu z Androidem, podczas gdy użytkownik aktualnie ogląda określony fragment.aktualizowanie podglądu stron z fragmentami w nowej kolejności

Mam ustawić wywołanie notifyDataSetChanged(), gdy nowe dane są pobierane z serwera, ale wydaje się, że przechowują buforowaną wersję slajdów po lewej i prawej stronie aktualnie wyświetlanego slajdu, które potencjalnie ulegnie zmianie z kolejność. Przyjrzałem się temu tematowi: ViewPager PagerAdapter not updating the View i zaimplementowałem pierwsze rozwiązanie, które działa dobrze, inne niż ładuje bieżący slajd, który jest oglądany, co nie zadziała w moich celach. Wziąłem płytko-nurkowe spojrzenie na implementację metody setTag() zaproponowanej na tej samej stronie w drugiej odpowiedzi, która działałaby na rzecz aktualizacji informacji na slajdach, ale nie pomoże mi to w zmianie kolejności.

Czy jest jakiś sposób, że mogę zmienić kolejność wszystkich slajdów za kulisami bez powodowania jakichkolwiek zniekształceń w aktualnie wyświetlanym slajdzie?

TIA

EDIT: dodanie kodu i prosząc o jakiś dalszych wyjaśnień

To moja klasa adaptera.

private class ScreenSlidePagerAdapter extends FragmentPagerAdapter { 
    ContestEntriesModel entries; 

    public ScreenSlidePagerAdapter(FragmentManager fm, ContestEntriesModel Entries) { 
     super(fm); 
     this.entries = Entries; 
    } 

    @Override 
    public long getItemId(int position) { 
     return entries.entries[position].ContestEntryId; 

    } 

    @Override 
    public int getItemPosition(Object object) { 
     android.support.v4.app.Fragment f = (android.support.v4.app.Fragment)object; 
     for(int i = 0; i < getCount(); i++){ 

      android.support.v4.app.Fragment fragment = getItem(i); 
      if(f.equals(fragment)){ 
       return i; 
      } 
     } 
     return POSITION_NONE; 
    } 


    @Override 
    public android.support.v4.app.Fragment getItem(int position) { 

     long entryId = getItemId(position); 
     //Log.d("EntryIds",Integer.toString(entryId)); 
     if(mItems.get(entryId) != null) { 
      return mItems.get(entryId); 
     } 
     Fragment f = ScreenSlidePageFragment.create(position); 
     mItems.put(entryId, f); 
     return f; 
    } 

    @Override 
    public int getCount() { 
     return NUM_PAGES; 
    } 
} 

A oto co używam, gdy nowy ładunek zstępuje z serwera:

@Override 
    protected void onPostExecute(ContestEntriesModel entries) { 
     Fragment currentFragment = ContestEntries.mItems.get(ContestEntries.CurrentEntryId); 
     Log.d("fromUpdate",Long.toString(ContestEntries.CurrentEntryId)); 
     ContestEntries.Entries = entries; 
     ContestEntries.NUM_PAGES = ContestEntries.Entries.entries.length; 
     ContestEntries.mPagerAdapter.notifyDataSetChanged(); 
     ContestEntries.mPager.setCurrentItem(ContestEntries.mPagerAdapter.getItemPosition(currentFragment)); 
    } 
+0

Wywołanie 'getItem (int)' w twojej implementacji spowoduje utworzenie nowego Fragmentu za każdym razem, ponieważ nie zaimplementowałeś jakiejś formy buforowania. Podczas tworzenia nowego fragmentu za każdym razem, 'getItemPosition (Object)' zawsze zwraca 'POSITION_NONE', dlatego też ładuje bieżący slajd, na którym się znajdujesz. – Reinier

+0

ok, czy możesz wskazać mi źródło, w którym mogę się dowiedzieć, jak zaimplementować jakąś formę buforowania? Ponadto obiekt fragmentu, którego używam, nie ma metody newInstance() ... –

+0

Objaśnienie: bez buforowania z mojego przykładu Fragment przekazany jako 'Object' nigdy nie będzie równa wartości zwracanej przez' getItem (int) ', ponieważ odwołania do obiektów nie są takie same. Chociaż możesz to przezwyciężyć, wprowadzając metodę 'equals()' w swoim Fragmentie, to nadal znaczyłoby, że tworzysz nowy Fragment z każdym wywołaniem 'getItem (int)' - co jest bezużytecznym marnowaniem zasobów. – Reinier

Odpowiedz

6

Sprawdź my answer here. Kluczem jest zastąpienie obu getItemId(int) i getItemPosition(Object) w adapterze.

getItemId(int) służy do jednoznacznego identyfikowania stron w zestawie danych. getItemPosition(Object) służy do pobierania (zaktualizowanej) pozycji dla tej unikatowej strony w zestawie danych.

Aby zachować koncentrację na tej samej stronie przed aktualizacją i po jej zakończeniu (dodawanie/usuwanie stron), należy wywołać viewpager.setCurrentItem(int) dla nowej pozycji strony po wywołaniu .notifyDataSetChanged() na karcie.

+0

wygląda to bardzo obiecująco. Wprawdzie nie jestem programistą dla Androida i jest to jeden z moich pierwszych prawdziwych projektów. Przedstawię twoją sugestię, ale bądź przygotowany, żebym zadał więcej pytań na temat implementacji, jeśli nie masz nic przeciwko. –

+0

OK, natknąłem się na moje pierwsze wyzwanie. Sposób, w jaki to robię, polega na przekazywaniu całkowitej liczby "slajdów" z mojego serwera. Następnie wypełniam tablicę danymi, które nie są bezpośrednio powiązane z moim pageriem (bez prawdziwego "zestawu danych" per se) i w klasie rozszerzenia Fragment, właśnie wypełniam moje slajdy w oparciu o indeks tej tablicy, który jest przekazane przez mój mPageNumber. Dlatego nie sądzę, żebym miał prawdziwy "klucz", którego mogę użyć w twoim przykładzie getItemId() na twojej połączonej stronie. Mogę opublikować kod w moim OP, jeśli uważasz, że to pomogłoby. –

+0

Jakiego rodzaju przedmioty otrzymujesz z serwera? Czy nie zawierają one jakiejś formy unikalnego identyfikatora? W przeciwnym razie możesz utworzyć identyfikator np. przez mieszanie poszczególnych przedmiotów. Jako, że 'getItemId (int)' jest 'ViewPager' sposobem identyfikowania unikalnych pozycji stron, jest to droga, którą należy przejść, jeśli chodzi o posiadanie stron z dynamicznymi pozycjami. I tak - prawdopodobnie pomoże przykładowy kod. – Reinier

Powiązane problemy