android - sectionspageradapter - Actualice las imágenes en FragmentStatePagerAdapter para reanudar la actividad
fragmentstatepageradapter notifydatasetchanged (4)
He creado una actividad que utiliza FragmentStatePagerAdapter
para proporcionar una pequeña galería. Sin embargo, no puedo actualizarlo cuando se reanuda la actividad (después de regresar de otra actividad, por ejemplo). Cada vez que las dos primeras imágenes están en blanco, y solo después de deslizar dos imágenes hacia un lado, se actualizan. Ninguna de las respuestas que encontré funcionó (especialmente sobreponer getItemPosition()
)
Lo configuré así:
mPagerAdapter = new PhotosPagerAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.photosViewPager);
mPager.setAdapter(mPagerAdapter);
Luego tengo la clase FragmentStatePagerAdapter:
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;
}
}
Como probablemente habrá notado, lanzo RuntimeException en getItemPosition, porque quería verificar cuándo se llama. Y no se llama hasta que agrego algo a la lista que contiene mis imágenes. Entonces la clase ImageFragment:
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();
}
}
El código es un poco desordenado después de que intenté arreglarlo ... Pero: eliminar onDestroyView()
no funciona. He puesto mPagerAdapter.notifyDataSetChanged()
en varios lugares que deben llamarse (como onResume()
), sin ningún resultado. Me estoy desesperando un poco con eso.
En lugar de devolver POSITION_NONE
y volver a crear todos los fragmentos, puede hacer lo que sugerí aquí: ¿ Actualizar ViewPager dinámicamente?
Nunca solo use POSITION_NONE uso
if(fragmentManager.getFragments().contains(object))
return POSITION_NONE;
else
return POSITION_UNCHANGED;
para evitar Fatal Exception: java.lang.IllegalStateException Fragment {} no se encuentra actualmente en FragmentManager
Tenía un problema similar al tuyo, después de algunas investigaciones, creé un buen script que evita recrear los fragmentos que ya existen pero que al mismo tiempo te permiten actualizar todos los fragmentos visibles / iniciados.
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);
}
Copie ese código en un nombre de archivo "FragmentAdvanceStatePagerAdapter.java". Ahora en su adaptador, extienda desde este y anule "getFragmentItem ()" & "updateFragmentItem ()". Siempre que llame a notificationdatachange (), se llamará a updateFragmentItem () con todo el fragmento ya creado. Cuando el adaptador necesite crear un nuevo fragmento, se llamará a getFragmentItem ().
Espero que salve y ayude a mucha gente :)
Buena suerte y feliz programación !!!
PD: su adaptador "getItem ()" debería ser "getFragmentItem ()" si usa esta clase.
Tratar con adaptadores de paginador de fragmentos puede ser un PITA.
Aquí hay algunos consejos útiles:
ViewPager PagerAdapter no actualiza la vista
¿Actualizar ViewPager dinámicamente?
En general, éste funciona el 99% del tiempo ...
Reemplace getItemPosition en su PagerAdapter de esta manera:
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
A veces, incluso esos no funcionan, tengo que usar el método de "fuerza bruta" y volver a crear toda la vista (desde onCreate en adelante) ...