Fragmento en ViewPager en Fragmento no se vuelve a cargar en el cambio de orientación

Estoy trabajando en el desarrollo de una aplicación de Android que utiliza ActionBarSherlock y ViewPagerIndicator. La actividad principal es una SherlockFragmentActivity y los usuarios navegan entre los fragmentos a través de pestañas en la barra de acción. Todas las pestañas son SherlockListFragments y la mayoría sólo contienen un ListView. Sin embargo, un fragmento (HeadlinesFragment) contiene un ViewPager, CirclePageIndicator, y un ListView para tablets, y sólo un ListView en teléfonos. ViewPager tiene un FragmentStatePagerAdapter que devuelve un SherlockFragment para los elementos.

El problema es que en el cambio de orientación (o cualquier cambio de configuración realmente), los fragmentos secundarios dentro del ViewPager no se vuelven a cargar y el CirclePagerIndicator no muestra ningún indicador como si el ViewPager está vacío. Sin embargo, el ListView se vuelve a cargar correctamente. En la carga inicial del fragmento, ViewPager funciona correctamente, pero no después del cambio de orientación.

MainActivity.java

public class MainActivity extends SherlockFragmentActivity { // =============== Variable Declaration ================ private HashMap<Integer, String> tabData; private HashMap<Integer, String> tabExtra; private Fragment currentFragment = null; private Fragment savedFragment = null; public ActionBar mActionBar; public MenuItem mRefresh; public static int mCurrentPos; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); HashMap<String, Object> savedData = (HashMap<String, Object>) getLastCustomNonConfigurationInstance(); if (savedData != null) { tabData = (HashMap<Integer, String>) savedData.get("tabData"); tabExtra = (HashMap<Integer, String>) savedData.get("tabExtra"); savedFragment = (Fragment) savedData.get("currentFragment"); mCurrentPos = ((Integer) savedData.get("pos")).intValue(); } else { tabData = (HashMap<Integer, String>) getIntent().getExtras().getSerializable("tabData"); tabExtra = (HashMap<Integer, String>) getIntent().getExtras().getSerializable("tabExtra"); mCurrentPos = 0; } mActionBar = getSupportActionBar(); Const.IsTablet = Utils.isTablet(MainActivity.this); //if (!Const.IsTablet) setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); TypedArray tabs = getResources().obtainTypedArray(R.array.TabBars); Tab tab; for (int i = 0; i < tabs.length(); i++) { String tabInfo[] = getResources().getStringArray(tabs.getResourceId(i, 0)); tab = mActionBar.newTab().setText(tabInfo[1]); if (tabInfo[0].equalsIgnoreCase("customizedNewsPage")) { tab.setTabListener(new MainTabListener<HeadlinesFragment>(MainActivity.this, i, HeadlinesFragment.class)); } mActionBar.addTab(tab); } tabs.recycle(); mActionBar.selectTab(mActionBar.getTabAt(mCurrentPos)); mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); //set navbar for ICS+ devices mActionBar.setBackgroundDrawable(getResources().getDrawable(R.drawable.navbar)); } @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { @Override public void handleMessage(Message message) { Bundle bundle = message.getData(); if (bundle.getInt("result") == Activity.RESULT_OK && bundle.getString("data") != null) { tabData.put(Integer.valueOf(bundle.getInt("tabPos")), bundle.getString("data")); DataType type = DataType.values()[bundle.getInt("type")]; switch (type) { case Headlines: ((HeadlinesFragment) currentFragment).setData(bundle.getString("data")); break; } tabData.put(Integer.valueOf(bundle.getInt("tabPos")), bundle.getString("data")); setRefreshActionButtonState(false); } } }; public Handler getHandler() { return mHandler; } @Override public Object onRetainCustomNonConfigurationInstance() { final HashMap<String, Object> savedData = new HashMap<String, Object>(); savedData.put("currentFragment", currentFragment); savedData.put("tabData", tabData); savedData.put("tabExtra", tabExtra); savedData.put("pos", Integer.valueOf(mCurrentPos)); return savedData; } private class MainTabListener<T extends Fragment> implements TabListener { private Fragment mFragment; private final SherlockFragmentActivity mActivity; private final int mPos; private final Class<T> mClass; /** Constructor used each time a new tab is created. */ public MainTabListener(SherlockFragmentActivity activity, int pos, Class<T> clz) { mActivity = activity; mPos = pos; mClass = clz; } @Override public void onTabSelected(Tab tab, FragmentTransaction ignoredFt) { FragmentManager fragMgr = ((FragmentActivity) mActivity).getSupportFragmentManager(); FragmentTransaction ft = fragMgr.beginTransaction(); // Check if the fragment is already initialized if (mFragment == null) { // If not, instantiate and add it to the activity mFragment = Fragment.instantiate(mActivity, mClass.getName()); Bundle args = new Bundle(); args.putString("data", tabData.get(mPos)); args.putInt("pos", mPos); mFragment.setArguments(args); ft.add(android.R.id.content, mFragment); } else { ft.attach(mFragment); } currentFragment = mFragment; mCurrentPos = mPos; mRefresh = null; ft.commit(); } @Override public void onTabUnselected(Tab tab, FragmentTransaction ignoredFt) { FragmentManager fragMgr = ((FragmentActivity) mActivity).getSupportFragmentManager(); FragmentTransaction ft = fragMgr.beginTransaction(); fragMgr.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); // Check if the fragment is already initialized if (mFragment == null) { mFragment = SherlockFragment.instantiate(mActivity, mClass.getName()); ft.add(android.R.id.content, mFragment); } else { ft.detach(mFragment); } currentFragment = null; ft.commit(); } @Override public void onTabReselected(Tab tab, FragmentTransaction ignoredFt) { onTabUnselected(tab, ignoredFt); onTabSelected(tab, ignoredFt); } } } 

HeadlinesFragment.java

 public class HeadlinesFragment extends SherlockListFragment implements SearchView.OnQueryTextListener, SearchView.SearchViewChangeMode, OnItemClickListener { private static final String LOG_TAG = "Headlines Fragment"; private JSONArray mHeadlines = new JSONArray(); private JSONArray mHeadlinesTop = new JSONArray(); private SearchView mSearchView; private MenuItem mSearchItem; private ViewPager mPager; private CirclePageIndicator mIndicator; private static int mPos; private int mRotatorImageWidth; private static HeadlinesFragment instance; private Tracker tracker; private Timer refreshTimer; private int refreshTime = 0;; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); instance = this; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mPos = getArguments().getInt("pos"); TypedArray tabs = getResources().obtainTypedArray(R.array.TabBars); String tabInfo[] = getResources().getStringArray(tabs.getResourceId(mPos, 0)); mRotatorImageWidth = Integer.valueOf(tabInfo[7]).intValue(); refreshTime = Integer.valueOf(tabInfo[4]).intValue(); tabs.recycle(); try { mHeadlines = new JSONArray(getArguments().getString("data")); } catch (NotFoundException e) { Log.e(LOG_TAG, "Error loading data", e); } catch (JSONException e) { Log.e(LOG_TAG, "Error loading data", e); } return inflater.inflate(R.layout.activity_headlines, container, false); } @SuppressWarnings("deprecation") @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); //if (Const.IsTablet) { if (((SIDHelpApplication) getActivity().getApplicationContext()).isTablet()) { try { mHeadlinesTop = new JSONArray(); JSONArray temp = new JSONArray(); for (int i = 0; i < mHeadlines.length(); i++) { if (i < 5) { mHeadlinesTop.put(mHeadlines.get(i)); } else { temp.put(mHeadlines.get(i)); } } mHeadlines = temp; } catch (JSONException e) { Log.e(LOG_TAG, "Error splitting off top 5", e); } mPager = (ViewPager) getActivity().findViewById(R.id.rotator); mPager.setOffscreenPageLimit(4); mPager.setAdapter(new RotatorAdapter(this, getActivity(), mHeadlinesTop, mRotatorImageWidth, mPos)); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { mPager.getLayoutParams().height = (int) Math.floor((((float) getResources().getInteger(R.integer.NewsImageHeight) / (float) getResources().getInteger(R.integer.NewsImageWidth)) * (float) getActivity().getWindowManager().getDefaultDisplay().getWidth())); } mIndicator = (CirclePageIndicator) getActivity().findViewById(R.id.indicator); mIndicator.setViewPager(mPager); } setListAdapter(new HeadlinesAdapter(getSherlockActivity(), mHeadlines)); getListView().setOnItemClickListener(this); getListView().setEmptyView(getActivity().findViewById(android.R.id.empty)); setAutoRefresh(); } public void setData(String data) { setData(data, false); } public void setData(String data, boolean search) { try { mHeadlines = new JSONArray(data); if (((SIDHelpApplication) getActivity().getApplicationContext()).isTablet() && !search) { mHeadlinesTop = new JSONArray(); try { JSONArray temp = new JSONArray(); for (int i = 0; i < mHeadlines.length(); i++) { if (i < 5) { mHeadlinesTop.put(mHeadlines.get(i)); } else { temp.put(mHeadlines.get(i)); } } mHeadlines = temp; } catch (JSONException e) { Log.e(LOG_TAG, "Error splitting off top 5", e); } ((RotatorAdapter) mPager.getAdapter()).setData(mHeadlinesTop); mPager.setVisibility(View.VISIBLE); mIndicator.setVisibility(View.VISIBLE); } else { getActivity().findViewById(android.R.id.empty).setVisibility(View.GONE); } if (search && mPager != null) { mPager.setVisibility(View.GONE); mIndicator.setVisibility(View.GONE); } ((HeadlinesAdapter) getListAdapter()).setData(mHeadlines); setAutoRefresh(); } catch (JSONException e) { Log.e(LOG_TAG, "Setting Data", e); } } public static HeadlinesFragment getInstance() { return instance; } } 

Activity_headlines.xml

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/llMainHeadline" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="false" android:focusableInTouchMode="true" android:background="@drawable/bg_img" > <android.support.v4.view.ViewPager android:id="@+id/rotator" android:layout_width="match_parent" android:layout_height="@dimen/headlines_rotator_height" android:layout_alignParentTop="true" android:background="@android:color/black" /> <com.viewpagerindicator.CirclePageIndicator android:id="@+id/indicator" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/rotator" android:background="@android:color/black" android:padding="10dp" /> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentBottom="true" android:layout_below="@id/indicator" android:cacheColorHint="#00000000" android:listSelector="@color/TableCellSelection" /> <TextView android:id="@android:id/empty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="@string/noResults" android:textSize="@dimen/noResult_text_size" android:textStyle="bold" android:visibility="gone" /> </RelativeLayout> 

RotatorAdapter.java

 public class RotatorAdapter extends FragmentStatePagerAdapter { private static final String LOG_TAG = "Rotator Adapter"; private Context mContext; private JSONArray mData; private int mImageWidth; private int mPos; public RotatorAdapter(SherlockListFragment fragment, Context context, JSONArray data, int imageWidth, int pos) { super(fragment.getChildFragmentManager()); mContext = context; mData = data; mImageWidth = imageWidth; mPos = pos; } @Override public int getCount() { return mData.length(); } @Override public Fragment getItem(int pos) { Fragment fragment = null; Bundle args = new Bundle(); try { JSONObject hdata = mData.getJSONObject(pos); args.putString("title", hdata.getString(mContext.getResources().getString(R.string.tag_title))); args.putString("category", hdata.getString(mContext.getResources().getString(R.string.tag_category))); args.putString("time", hdata.getString(mContext.getResources().getString(R.string.tag_time))); args.putString("newsID", hdata.getString(mContext.getResources().getString(R.string.tag_newsID))); args.putString("photoURL", hdata.getString(mContext.getResources().getString(R.string.tag_photoURL))); args.putInt("imageWidth", mImageWidth); args.putInt("pos", mPos); fragment = Fragment.instantiate(mContext, RotatorFragment.class.getName(), args); } catch (JSONException e) { Log.e(LOG_TAG, "Error getting data", e); } return fragment; } public void setData(JSONArray data) { mData = data; notifyDataSetChanged(); } } 

RotatorFragment.java

 public class RotatorFragment extends SherlockFragment implements OnClickListener { private static final String LOG_TAG = "Rotator Fragment"; private String mNewsID; private int mPos; private ImageLoader imageLoader = ImageLoader.getInstance(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_headlines_top_row, container, false); // Set the image ImageView image = (ImageView) view.findViewById(R.id.imgArticle); String photoURL = getArguments().getString("photoURL").replaceAll(" ", "%20"); imageLoader.displayImage(photoURL, image); // Set title, category, and time TextView headlineTitle = (TextView) view.findViewById(R.id.txtTitle); TextView headlineCategory = (TextView) view.findViewById(R.id.txtCategory); headlineTitle.setText(getArguments().getString("title")); headlineCategory.setText(String.format("%s - %s", getArguments().getString("category"), getArguments().getString("time"))); // Set article ID for onclick listener mNewsID = getArguments().getString("newsID"); mPos = getArguments().getInt("pos"); view.setOnClickListener(this); return view; } @Override public void onClick(View v) { // Load article data Log.i(LOG_TAG, "Loading Article"); Intent dataIntent = new Intent(getActivity(), DataLoader.class); Messenger dataMessenger = new Messenger(HeadlinesFragment.mHandler); dataIntent.putExtra("MESSENGER", dataMessenger); dataIntent.putExtra("tabPos", mPos); dataIntent.putExtra("type", DataType.HeadlinesArticle.ordinal()); String params[] = new String[] {mNewsID}; dataIntent.putExtra("params", params); getActivity().startService(dataIntent); } @Override public void onSaveInstanceState (Bundle outState) { // Don't save the fragment state } } 

One Solution collect form web for “Fragmento en ViewPager en Fragmento no se vuelve a cargar en el cambio de orientación”

Me di cuenta del problema. El problema era cuando la configuración cambiaba, Android destruiría y recrearía la Actividad, pero los Fragmentos no estaban siendo destruidos. Fueron agregados de nuevo al gerente y debido al código también estaban siendo recreados. Por lo tanto, el ViewPager que no se recreó cuando se creó el nuevo fragmento no lo hizo correctamente. La solución para esto fue en la función onTabSelected que hice una comprobación para el Fragmento ya existente en el gestor, y sólo se utiliza en lugar de volver a crearlo. También tuve que añadir etiquetas a cada Fragmento que se creó para poder encontrar el Fragmento que estaba buscando.

 if (mCurrentTag != null && mCurrentTag.equalsIgnoreCase(mTag) && fragMgr.findFragmentByTag(mCurrentTag) != null) { mFragment = fragMgr.findFragmentByTag(mCurrentTag); } 
  • No se puede crear una instancia del tipo PagerAdapter
  • Android FragmentStatePagerAdapter devuelve pantalla en blanco al recargar fragmentos de medio
  • Fragmentos que no se vuelven a crear por FragmentStatePagerAdapter después de volver a la instancia de Fragmento principal
  • El fragmento ya no existe para la clave f0: index 1
  • Cambio de la imagen de fondo del fragmento actual en viewpager
  • FragmentStatePagerAdapter fuga de memoria (fragmentos anidados con viewpager)
  • GetResources de FragmentStatePagerAdapter
  • Diferencia entre FragmentPagerAdapter y FragmentStatePagerAdapter
  • Cargar sólo un fragmento en ViewPager
  • Destruye el elemento del adaptador de ViewPager después de cambiar la orientación de la pantalla
  • Android setUserVisibleHint nunca se llama?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.