16

Utworzono działanie, które używa FragmentStatePagerAdapter, aby zapewnić małą galerię. Jednak nie mogę go odświeżyć, gdy aktywność zostanie wznowiona (na przykład po powrocie z innej aktywności). Za każdym razem, gdy pierwsze dwa zdjęcia będą puste i dopiero po przesunięciu dwóch obrazów na bok, zostaną odświeżone. Żadna z odpowiedzi nie znalazłem pracę (zwłaszcza nadrzędnych getItemPosition())Odśwież obrazy w FragmentStatePagerAdapter o wznowieniu aktywności

ustawić go tak:

mPagerAdapter = new PhotosPagerAdapter(getSupportFragmentManager()); 
mPager = (ViewPager) findViewById(R.id.photosViewPager); 
mPager.setAdapter(mPagerAdapter); 

Wtedy mam FragmentStatePagerAdapter Klasa:

private class PhotosPagerAdapter extends FragmentStatePagerAdapter{ 

    public PhotosPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public int getCount() { 
     return photos.size(); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     ImageFragment f = new ImageFragment(position); 
     return f; 
    } 

    @Override 
    public int getItemPosition(Object object) { 
     throw new RuntimeException(); 
     //return POSITION_NONE; 
    } 

} 

Jak zapewne zauważyliście, Rzucam RuntimeException w getItemPosition, ponieważ chciałem sprawdzić, kiedy zostanie wywołany. I nie jest wywoływana, dopóki nie dodaję czegoś do listy zawierającej moje zdjęcia. Następnie ImageFragment klasa:

public class ImageFragment extends Fragment{ 

    int position; 
    Bitmap mBitmap; 
    int width; 
    int height; 
    ImageView img; 

    public ImageFragment(){ 
    } 

    public ImageFragment(int position){ 
     this.position = position; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 

     img = new ImageView(container.getContext()); 
     img.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 
     width = container.getWidth(); 
     height = container.getHeight(); 

     loadBitmap(); 

     return img; 
    }  

    public void loadBitmap(){ 
     if (img == null){ 
      return; 
     } 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeFile(photos.get(position), options); 
     options.inSampleSize = calculateInSampleSize(options, width/2, height/2); 
     options.inJustDecodeBounds = false; 
     mBitmap = BitmapFactory 
       .decodeFile(photos.get(position), options);   

     img.setImageBitmap(mBitmap); 
    } 


    @Override 
    public void onDestroyView() { 
     mBitmap.recycle(); 
     super.onDestroyView(); 
    }  
} 

Code jest trochę brudny po tym, jak próbował to naprawić ... Ale: usuwanie onDestroyView() nie działa. Umieściłem mPagerAdapter.notifyDataSetChanged() w kilku miejscach, które muszą zostać wywołane (jak onResume()), bez rezultatu. Trochę z tym rozpaczliwie.

Odpowiedz

31

Radzenie sobie z adapterami pager fragmentów może być PITA.

Oto kilka pomocnych wskazówek:

ViewPager PagerAdapter not updating the View

Update ViewPager dynamically?

Generalnie ten pracuje 99% czasu ...

Zastąp getItemPosition w PagerAdapter tak:

@Override 
public int getItemPosition(Object object) { 
    return POSITION_NONE; 
} 

Czasami nawet te nie działają, muszę użyć metody "brute force" i odtworzyć cały widok ponownie (od onCreate) ...

+0

Jesteś geniuszem! Cały dzień próbowałem wszystkiego, ale to zadziałało idealnie! –

+0

Działa zgodnie z wywołaniem adaptera notifyDataSetChanged(). – user465363

1

nie wystarczy użyć POSITION_NONE używać

if(fragmentManager.getFragments().contains(object)) 
    return POSITION_NONE; 
else 
    return POSITION_UNCHANGED; 

uniknąć krytyczny wyjątek: java.lang.IllegalStateException Fragment {} nie jest obecnie w FragmentManager

+0

To nie działa dla mnie –

4

Miałem podobny problem, jak twój, po przeprowadzeniu pewnych badań stworzyłem ładny skrypt, który unikał ponownego tworzenia fragmentów, które już istnieją, ale jednocześnie umożliwia aktualizację wszystkich widocznych/zainicjowanych fragmentów.

import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentStatePagerAdapter; 
import android.view.ViewGroup; 

import java.util.WeakHashMap; 

/** 
* Created by TheCobra on 9/17/15. 
*/ 
public abstract class FragmentAdvanceStatePagerAdapter extends FragmentStatePagerAdapter 
{ 
    private WeakHashMap<Integer, Fragment> mFragments; 

    public FragmentAdvanceStatePagerAdapter(FragmentManager fm) 
    { 
     super(fm); 
     mFragments = new WeakHashMap<Integer, Fragment>(); 
    } 

    @Override 
    public Fragment getItem(int position) 
    { 
     Fragment item = getFragmentItem(position); 
     mFragments.put(Integer.valueOf(position), item); 
     return item; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) 
    { 
     super.destroyItem(container, position, object); 
     Integer key = Integer.valueOf(position); 
     if (mFragments.containsKey(key)) 
     { 
      mFragments.remove(key); 
     } 
    } 

    @Override 
    public void notifyDataSetChanged() 
    { 
     super.notifyDataSetChanged(); 
     for (Integer position : mFragments.keySet()) 
     { 
      //Make sure we only update fragments that should be seen 
      if (position != null && mFragments.get(position) != null && position.intValue() < getCount()) 
      { 
       updateFragmentItem(position, mFragments.get(position)); 
      } 
     } 
    } 

    @Override 
    public int getItemPosition(Object object) 
    { 
     //If the object is a fragment, check to see if we have it in the hashmap 
     if (object instanceof Fragment) 
     { 
      int position = findFragmentPositionHashMap((Fragment) object); 
      //If fragment found in the hashmap check if it should be shown 
      if (position >= 0) 
      { 
       //Return POSITION_NONE if it shouldn't be display 
       return (position >= getCount()? POSITION_NONE : position); 
      } 
     } 

     return super.getItemPosition(object); 
    } 

    /** 
    * Find the location of a fragment in the hashmap if it being view 
    * @param object the Fragment we want to check for 
    * @return the position if found else -1 
    */ 
    protected int findFragmentPositionHashMap(Fragment object) 
    { 
     for (Integer position : mFragments.keySet()) 
     { 
      if (position != null && 
       mFragments.get(position) != null && 
       mFragments.get(position) == object) 
      { 
       return position; 
      } 
     } 

     return -1; 
    } 

    public abstract Fragment getFragmentItem(int position); 
    public abstract void updateFragmentItem(int position, Fragment fragment); 
} 

Skopiuj ten kod do nazwy pliku "FragmentAdvanceStatePagerAdapter.java". Teraz w swoim adapterze, rozciągnij się od tego i nadpisaj "getFragmentItem()" & "updateFragmentItem()". Za każdym razem, gdy wywołasz funkcję notifydiazange(), funkcja updateFragmentItem() zostanie wywołana wraz z całym utworzonym fragmentem. Kiedy adapter musi utworzyć nowy fragment, zostanie wywołana funkcja getFragmentItem().

Mam nadzieję, że uratować i pomóc wielu ludziom :)

Powodzenia i szczęśliwego Programowanie !!!

P.S. twój adapter "getItem()" powinien być "getFragmentItem()", jeśli używasz tej klasy.

+0

Zaktualizowałem, aby naprawić błąd znaleziony w kodzie. – TheCobra

+0

Niesamowity kod !! To działa jak urok. Najlepsza odpowiedź tutaj – davidrelgr

Powiązane problemy