ViewPager no se actualiza con FragmentStatePagerAdapter

Tengo dos fragments , Fragment A y Fragment B Fragment A enumera todos los productos y el Fragment B muestra detalles sobre el producto y sus imágenes.

Fragment A llama al Fragment B y el Fragment B obtiene datos del servicio web y se establece en ViewPager con el Adapter . Inicialmente muestra la imagen correcta pero después siempre tiene la misma imagen.

Si adapter.notifyDataSetChanged() de cualquier evento de clic en el fragmento B entonces funciona perfectamente pero tenemos que mostrar tan pronto como el fragmento B es visible

Por favor, mira el código.

  public class ImageAdapter extends FragmentStatePagerAdapter { private List<String> pImageURL; public ImageAdapter(FragmentManager fm, List<String> imageURL) { super(fm); // TODO Auto-generated constructor stub pImageURL = imageURL; Utility.showLog("PagerAdapter URL", pImageURL.toString()); } @Override public Fragment getItem(int position) { // TODO Auto-generated method stub String imageURL = pImageURL.get(position); PImageFragment imageFragment = (PImageFragment) PImageFragment.getInstance(); imageFragment.setProductImage(imageURL); return imageFragment; } @Override public int getItemPosition(Object object) { PImageFragment pFragment = (PImageFragment) object; String URL = pFragment.getProductImage(); int position = pImageURL.indexOf(URL); if (position>=0) URL = pImageURL.get(position); if (position>=0) return position; else return POSITION_NONE; } @Override public int getCount() { // TODO Auto-generated method stub return pImageURL.size(); } } 

Fragmento B

  // Image Loading Process String p_images = model.getProdutImageURL(); imageUrl = new ArrayList<String>(); if (p_images.contains(",")) imageUrl.addAll(Arrays.asList(p_images.split(","))); else imageUrl.add(p_images); mAdapter = new ImageAdapter(getChildFragmentManager(), imageUrl); vPager.setPageTransformer(true, new DepthPageTransformer()); vPager.setAdapter(mAdapter); mAdapter.notifyDataSetChanged(); 

Fragmento de la imagen

 public class PImageFragment extends Fragment { private static final String TAG = "Product_Images_Fragment"; private View rootView; private ImageView ivProductImage; private String imageURL; @Override @Nullable public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub rootView = inflater.inflate(R.layout.p_detail_images, container, false); bindComponents(rootView); loadImages(imageURL); return rootView; } public static Fragment getInstance() { Fragment fragment = new PImageFragment(); return fragment; } public void setProductImage(String image_url) { imageURL = image_url; Utility.showLog(TAG + "Received URL : ", imageURL.toString()); } public String getProductImage() { return imageURL; } private void bindComponents(View v) { // TODO Auto-generated method stub ivProductImage = (ImageView) v.findViewById(R.id.ivProductImage); } private void loadImages(String image_url) { Utility.showLog(TAG, "http://baryapp.com/kickzexchange/assets/products/" + image_url); final ProgressBar pBar = (ProgressBar) rootView .findViewById(R.id.pBarLoader); pBar.setVisibility(View.VISIBLE); ImageLoader imgLoader = VolleySingleton.getInstance().getImageLoader(); imgLoader.get("http://baryapp.com/kickzexchange/assets/products/" + image_url, new ImageListener() { @Override public void onErrorResponse(VolleyError vError) { // TODO Auto-generated method stub Utility.showLog(TAG, vError.getLocalizedMessage() + ""); } @Override public void onResponse(ImageContainer response, boolean result) { // TODO Auto-generated method stub if (response.getBitmap() != null) { ivProductImage.setImageBitmap(response.getBitmap()); pBar.setVisibility(View.GONE); } } }); } } 

ACTUALIZAR

  // This is how fragment A calls fragment B ProductDetail pDetail = new ProductDetail(); Bundle bundle = new Bundle(); bundle.putString("product_id", productList.get(position).getProductID()); bundle.putString("product_title", productList.get(position).getProductTitle()); pDetail.setArguments(bundle); ((MyTabActivity) mActivity).navigateFragment(Utility.BUY_TAB, pDetail, true); 

ÚLTIMA ACTUALIZACIÓN

  public void navigateFragment(String tag, Fragment fragment, boolean shouldAdd) { FragmentManager manager = getSupportFragmentManager(); FragmentTransaction ft = manager.beginTransaction(); if (shouldAdd) mStacks.get(tag).push(fragment); // push fragment on stack if (mCurrentFragment != null) { saveFragmentState(mCurrentFragment.getClass().getName(), mCurrentFragment); } mCurrentFragment = fragment; restoreFragmentState(fragment.getClass().getName(), fragment); ft.replace(android.R.id.tabcontent, fragment); ft.commit(); } @Override protected void onSaveInstanceState(Bundle outState) { // TODO Auto-generated method stub super.onSaveInstanceState(outState); Bundle fragmentStates = new Bundle(mFragmentStates.size()); for (Map.Entry<String, Fragment.SavedState> entry : mFragmentStates.entrySet()) { fragmentStates.putParcelable(entry.getKey(), entry.getValue()); } outState.putParcelable(KEY_FRAGMENT_STATES, fragmentStates); } private void saveFragmentState(String id, Fragment fragment) { Fragment.SavedState fragmentState = getSupportFragmentManager().saveFragmentInstanceState(fragment); mFragmentStates.put(id, fragmentState); } private void restoreFragmentState(String id, Fragment fragment) { Fragment.SavedState fragmentState = mFragmentStates.remove(id); if (fragmentState != null) { if (!fragment.isAdded()) fragment.setInitialSavedState(fragmentState); } } 

Cualquier ayuda / idea es muy apreciada.

Puede utilizar la siguiente clase base PagerFragment para sus fragmentos e implementar el método onVisible según sea necesario:

 public abstract class PagerFragment extends Fragment { private boolean mCalled = false; private boolean mWasVisible = false; private boolean mIsResumed = false; private boolean mIsPaused = false; protected void onVisible() { mCalled = true; } protected void onHide() { mCalled = true; } /** * {@inheritDoc} * * @see android.app.Fragment#onAttach(android.app.Activity) */ @Override public void onAttach(Activity activity) { super.onAttach(activity); } /** * {@inheritDoc} * * @see android.app.Fragment#onDetach() */ @Override public void onDetach() { super.onDetach(); } /** * {@inheritDoc} * * @see android.app.Fragment#onResume() */ @Override public void onResume() { super.onResume(); mIsPaused = false; mIsResumed = true; setUserVisibleHint(getUserVisibleHint()); } /** * {@inheritDoc} * * @see android.app.Fragment#onPause() */ @Override public void onPause() { mIsPaused = true; mIsResumed = false; setUserVisibleHint(getUserVisibleHint()); super.onPause(); } /** * {@inheritDoc} * * @see android.app.Fragment#setUserVisibleHint(boolean) */ @Override public void setUserVisibleHint(boolean visible) { super.setUserVisibleHint(visible); mCalled = false; if (mIsResumed) { if (visible) { performVisible(); mWasVisible = visible; } else { performHide(); mWasVisible = visible; } } else if (mIsPaused && mWasVisible) { performHide(); mWasVisible = visible; } } private void performVisible() { onVisible(); if (!mCalled) { throw new SuperNotCalledException("PagerFragment " + this + " did not call through to super.onVisible()"); } } private void performHide() { onHide(); if (!mCalled) { throw new SuperNotCalledException("PagerFragment " + this + " did not call through to super.onHide()"); } } } 

O simplemente precargar los datos en el Fragment A y notificar al adaptador cuando los datos fueron cargados y luego cambiar las páginas. Siempre es posible agregar y eliminar Fragmentos dinámicamente desde un ViewPager. Así que también puede tratar de eliminar el fragmento con los datos antiguos y crear uno nuevo después.

No ha mostrado la parte crítica, es decir, MyTabActivity.navigateFragment() .

Creo que usted está intentando reutilizar la instancia existente del fragmento B, y pasar los nuevos datos por Fragment.setArguments()

SetArguments no tiene uso después de que se crea Fragment

ya sea

  1. Crear una nueva instancia de Fragmento B cada vez y reemplazar la existente, o
  2. Pasar los nuevos datos utilizando funciones personalizadas en el fragmento

Sugiero el método 1, porque al hacer esto, sus datos se mantienen incluso si la actividad de recreación, por ejemplo, la rotación de la pantalla. Para el método 2, necesita trabajo adicional para controlar la actividad recreate.

Si lo entiendo correctamente, puede intentar usar el onPageSelected y dependiendo de la posición actualice sus fragmentos en qué página está seleccionada.

  viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { //use this to run when your fragment is visible } @Override public void onPageScrollStateChanged(int state) { } }); 

Como sabrás, cargas la imagen en un proceso en segundo plano. Es decir, utilizando volley biblioteca .

Su adapter.notifyDataSetChanged() se está llamando incluso antes de que el proceso esté terminado. Pero como le dijiste cuando lo llamas en el botón haga clic en funciona, entonces la solución es simple.

Llame a su adapter.notifyDataSetChanged() después de completar el proceso de fondo.

Es decir dentro: –

  @Override public void onResponse(ImageContainer response, boolean result) { // TODO Auto-generated method stub if (response.getBitmap() != null) { ivProductImage.setImageBitmap(response.getBitmap()); pBar.setVisibility(View.GONE); adapter.notifyDataSetChanged(); } } }); 

Cuando se utiliza FragmentStatePagerAdapter, getItem () se llama sólo una vez, por lo que inicialmente tiene la imagen correcta, pero luego permanece igual.

Deberá volver a cargar sus datos mediante una interfaz de devolución de llamada. Por lo tanto, cuando se selecciona uno de los elementos del fragmento A, se vuelven a cargar datos en el fragmento B. Para ello, tendrá que agregar

 public void reloadData() { //relaod your data here } 

A continuación, cree una interfaz de devolución de llamada en el fragmento A de este modo

 public interface itemSelectedListener { void onItemSelected(View view, int position) } 

Implementar esta interfaz en la actividad que contiene ambos fragmentos

en

 onItemSelected() { MyFragmentB myFragmentB = ...//get your fragment myFragmentB.reloadData(); } 

Finalmente he resuelto la respuesta. Fragment B estaba guardando en navigateFragment , se ha evitado por la siguiente línea y funcionó.

  if (mCurrentFragment != null) { if (mCurrentFragment instanceof GetProducts) saveFragmentState(mCurrentFragment.getClass().getName(), mCurrentFragment); } 
  • Android setUserVisibleHint nunca se llama?
  • La aplicación se bloquea al asignar un nuevo adaptador a mi ViewPager
  • Android - fragmento de niño no carga la segunda vez dentro de FragmentStatePagerAdapter
  • FragmentPagerAdapter y FragmentStatePagerAdapter
  • Segundo conjunto de pestañas en un fragmento de Android
  • ViewPager + FragmentStatePageAdapter: ¿qué significa esta advertencia "no actualizada en línea"?
  • FragmentStatePageAdapter: Múltiples elementos visibles al mismo tiempo - ¿Cómo centrar una página específica?
  • No se puede crear una instancia del tipo PagerAdapter
  • Ver Pager Crash Null Pointer Excepción debido a navegar de nuevo al fragmento antiguo - Android
  • GetResources de FragmentStatePagerAdapter
  • Android FragmentStatePagerAdapter devuelve pantalla en blanco al recargar fragmentos de medio
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.