Frammento con ViewPager all'interno di frammento e FragmentStatePagerAdapter risultati in exception (con esempi completi)

Ho un frammento semplice con un ViewPager.

Sto utilizzando la libreria di supporto aggiornata, v4 rev18!

  • Binder di java Android FAILED BINDER TRANSACTION?
  • TreeView come funzionalità Android
  • Leggere il file Assets come string
  • Connessione a google Play Services non rioutput
  • Come verificare se Facebook è installato Android
  • devicePolicyManager.lockNow () non funziona per Motorola Tablets
  • Se mostro il frammento secondario la prima volta, tutto funziona bene, se torno e lo mostro di nuovo, l'applicazione si blocca con l'exception seguente:

    Ho un esempio completo che mostra, quando si verifica la seguente exception:

    java.lang.NullPointerException at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:569) at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:211) at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1281) at android.view.View.dispatchRestoreInstanceState(View.java:12043) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2688) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2694) at android.view.View.restoreHierarchyState(View.java:12021) at android.support.v4.app.Fragment.restoreViewState(Fragment.java:425) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:949) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440) at android.os.Handler.handleCallback(Handler.java:615) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4800) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565) at dalvik.system.NativeStart.main(Native Method) 

    Sono in grado di utilizzare ViewPager in un frammento di figlio in each altro modo, ma non posso funzionare se aggiungo o rimuovo i frammenti secondari manualmente e utilizzando un frammento FragmentStatePagerAdapter nei frammenti secondari …

    Il seguente esempio dovrebbe funzionare, ma non … ho già aggiunto un codice che risolve alcuni problemi, ma non risolve tutti i problemi …

     import java.lang.reflect.Field; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.TextView; public class TestActivity extends FragmentActivity implements OnClickListener { private Fragment fragment1; private Fragment fragment2; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_main); fragment1 = getSupportFragmentManager().findFragmentByTag("fragment1"); fragment2 = getSupportFragmentManager().findFragmentByTag("fragment2"); } @Override public void onClick(View v) { Fragment nextFragment = null; String nextFragmentTag = null; if (v.getId() == R.id.button1) { if (fragment1 == null) fragment1 = ContainerFragment.newInstance(1); nextFragment = fragment1; nextFragmentTag = "fragment1"; } else if (v.getId() == R.id.button2) { if (fragment2 == null) fragment2 = ContainerFragment.newInstance(2); nextFragment = fragment2; nextFragmentTag = "fragment2"; } FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.main, nextFragment, nextFragmentTag); transaction.addToBackStack(null); transaction.commit(); } public static class MainPagerAdapter extends FragmentStatePagerAdapter { public int button; public MainPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { return SubFragment.newInstance(button, i); } @Override public int getCount() { return 10; } } public static class ContainerFragment extends Fragment { static ContainerFragment newInstance(int pos) { ContainerFragment f = new ContainerFragment(); Bundle args = new Bundle(); args.putInt("pos", pos); f.setArguments(args); return f; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.view_pager, container, false); ViewPager pager = (ViewPager) rootView.findViewById(R.id.pager); MainPagerAdapter adapter = new MainPagerAdapter(getChildFragmentManager()); adapter.button = getArguments().getInt("pos"); pager.setAdapter(adapter); return rootView; } // --------------------------------------------------------------- // HACK FIX für java.lang.IllegalStateException: No activity // --------------------------------------------------------------- private static final Field sChildFragmentManagerField; static { Field f = null; try { f = android.support.v4.app.Fragment.class.getDeclaredField("mChildFragmentManager"); f.setAccessible(true); } catch (NoSuchFieldException e) { } sChildFragmentManagerField = f; } @Override public void onDetach() { super.onDetach(); if (sChildFragmentManagerField != null) { try { sChildFragmentManagerField.set(this, null); } catch (Exception e) { } } } } public static class SubFragment extends Fragment { static SubFragment newInstance(int button, int pos) { SubFragment f = new SubFragment(); Bundle args = new Bundle(); args.putString("key", "Button " + button + "Fragment " + pos); f.setArguments(args); return f; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.test_subfragment, container, false); ((TextView) rootView.findViewById(R.id.tv1)).setText(getArguments().getString("key")); return rootView; } } } 

    per completezza, aggiungo anche i file xml:

    test_main.xml

     <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClick" android:text="Button1" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClick" android:text="Button2" /> </LinearLayout> </FrameLayout> 

    test_subfragment.xml

     <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv1" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textSize="50sp" /> 

    view_pager.xml

     <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/llContainer" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> 

  • Android: disegno di SQLite one-to-many
  • setText non riesce a mostrare un numero come text in un TextView
  • Strategia chiave primaria Android (applicazione distribuita)
  • Nascondi barra di sistema nella tavoletta di fagioli di gelatina (radicata)
  • ImageView senza definizione xml
  • Punto principale in android: il nome è veramente richiesto?
  • One Solution collect form web for “Frammento con ViewPager all'interno di frammento e FragmentStatePagerAdapter risultati in exception (con esempi completi)”

    Aggiungere un FrameLayout aggiuntivo al layout dell'attività principale. È qui che metti il ​​frammento.

     <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClick" android:text="Button1" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClick" android:text="Button2" /> <!-- add this --> <FrameLayout android:id="@+id/fragment_frame" android:layout_width="match_parent" android:layout_height="match_parent" > </FrameLayout> </LinearLayout> </FrameLayout> 

    Poiché aggiungete i tuoi frammenti al BackStack , non c'è bisogno di salvare un'istanza . Questo è il motivo per cui app si blocca. Adattare il metodo onClick() come segue:

      @Override public void onClick(View v) { Fragment nextFragment = null; String nextFragmentTag = null; if (v.getId() == R.id.button1) { nextFragment = ContainerFragment.newInstance(1); nextFragmentTag = "fragment1"; } else if (v.getId() == R.id.button2) { nextFragment = ContainerFragment.newInstance(2); nextFragmentTag = "fragment2"; } FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_frame, nextFragment, nextFragmentTag); transaction.addToBackStack(null); transaction.commit(); } 

    Ho provato il codice. La modifica dei frammenti con i pulsanti funziona e lo stato in cui è stato lasciato il ViewPager quando viene ritentato è conservato .

    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.