2016-03-02 30 views
14

Sto usando un frammento ViewPager che ha due frammenti da bambini. Questa grande opera, tuttavia quando si sostituisce la frammento ViewPager da un altro frammento e sostituire questo frammento dal frammento ViewPager miei crash dell'applicazione con il seguente NullPointerException:NullPointerException quando si visualizza un ViewPager una seconda volta

java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference 
    at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:667) 
    at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:211) 
    at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1319) 
    at android.view.View.dispatchRestoreInstanceState(View.java:13756) 
    at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2888) 
    at android.view.View.restoreHierarchyState(View.java:13734) 
    at android.support.v4.app.Fragment.restoreViewState(Fragment.java:468) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1094) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248) 
    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738) 
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613) 
    at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517) 
    at android.os.Handler.handleCallback(Handler.java:739) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5294) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699) 

mio ViewPager frammento è costituito dai seguenti codice sorgente instanciating i due bambini frammenti nel caso in cui siano nulli. Inoltre, l'implementazione ViewPagerAdapter viene instanciata e assegnata allo ViewPager.

public class ConnectionPasswordViewPagerFragment extends Fragment 
{ 
    private ViewPager vpConnectionPassword; 
    private ConnectionPasswordViewPagerAdapter paConnectionPassword; 
    private ConnectionPasswordGeneratorMACAddress passwordGeneratorMACAddress; 
    private ConnectionPasswordGeneratorSerialNumber passwordGeneratorSerialNumber; 

    public ConnectionPasswordViewPagerFragment() 
    { 
    // Required empty public constructor 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 

    if ((this.passwordGeneratorSerialNumber == null) && (this.passwordGeneratorMACAddress == null)) 
    { 
     this.passwordGeneratorMACAddress = new ConnectionPasswordGeneratorMACAddress(); 
     this.passwordGeneratorSerialNumber = new ConnectionPasswordGeneratorSerialNumber(); 
    } 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) 
    { 
    // Inflate the layout for this fragment 
    return inflater.inflate(R.layout.fragment_connection_password_view_pager, container, false); 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) 
    { 
    super.onActivityCreated(savedInstanceState); 

    /*if (this.paConnectionPassword == null) 
    {*/ 
     this.paConnectionPassword = new ConnectionPasswordViewPagerAdapter(this.getChildFragmentManager(), this.getActivity(), this.passwordGeneratorMACAddress, this.passwordGeneratorSerialNumber); 
    //} 
    this.vpConnectionPassword = (ViewPager) this.getActivity().findViewById(R.id.vpConnectionPassword); 
    this.vpConnectionPassword.setAdapter(this.paConnectionPassword); 
    } 
} 

Il ViewPagerAdapter mostrato sotto attuazione mantiene il riferimento ai frammenti bambino in un ArrayList e implementa le metods getItem(), getCount() nonché getPageTitle(). La classe ViewPagerFragment estende semplicemente la classe di supporto Fragment e fornisce il metodo astratto getPageTitleStringID() implementato dai frammenti figlio.

public class ConnectionPasswordViewPagerAdapter extends FragmentStatePagerAdapter 
{ 
    private static final byte NUMBER_OF_FRAGMENTS = (byte) 2; 

    private ArrayList<ViewPagerFragment> childFragments; 
    private Activity displayActivity; 

    public ConnectionPasswordViewPagerAdapter(FragmentManager fragmentMgm, Activity displayAct, ConnectionPasswordGeneratorMACAddress generatorMACAddress, ConnectionPasswordGeneratorSerialNumber generatorSerialNumber) 
    { 
    super(fragmentMgm); 

    this.childFragments = new ArrayList<>(ConnectionPasswordViewPagerAdapter.NUMBER_OF_FRAGMENTS); 
    this.setDisplayActivity(displayAct); 
    if (generatorMACAddress != null) 
    { 
     this.childFragments.add(generatorMACAddress); 
    } 
    if (generatorSerialNumber != null) 
    { 
     this.childFragments.add(generatorSerialNumber); 
    } 
    } 

    public Activity getDisplayActivity() 
    { 
    return this.displayActivity; 
    } 

    public void setDisplayActivity(Activity value) 
    { 
    this.displayActivity = value; 
    } 

    @Override 
    public Fragment getItem(int position) 
    { 
    return this.childFragments.get(position); 
    } 

    @Override 
    public int getCount() 
    { 
    return ConnectionPasswordViewPagerAdapter.NUMBER_OF_FRAGMENTS; 
    } 

    @Override 
    public CharSequence getPageTitle(int position) 
    { 
    return this.getDisplayActivity().getString(this.childFragments.get(position).getPageTitleStringID()); 
    } 
} 

Grazie per il vostro aiuto!

+0

Come hai fatto a risolvere questo? – rupinderjeet

risposta

6

Ho risolto il problema semplicemente creando il frammento che contiene il visualizza il cercapersone ogni volta che chiamo il metodo replace del gestore framment di supporto.

public void onSwitchToConnectionPasswordGenerator(View clickedView) 
{ 
    this.fragConnectionPassword = new ConnectionPasswordViewPagerFragment(); 
    this.getSupportFragmentManager().beginTransaction().replace(R.id.flFragmentContainer, this.fragConnectionPassword).commitAllowingStateLoss(); 
} 
+0

Sto utilizzando l'account di un amico, ma puoi dare un'occhiata alla mia domanda? Sto avendo più o meno la situazione esatta. http://stackoverflow.com/questions/42213051/no-indication-as-to-where-npe-could-occur?noredirect=1#comment71590739_42213051 – jlively

2

Credo che il tuo Viewpager è frammento, e questo frammento ho setRetainInstance impostata su true (ho questo errore anche quando provo a mantenere il frammento genitore)

+0

Grazie! Suppongo che tu voglia dire che dovrei chiamare 'setRetainInstance (false)'. Dove dovrei chiamare questo metodo? – Lukas

0

Meglio modo è quello che si può controllare per FragmentManager per ottenere Frammento se c'è, se non poi creare una nuova istanza come segue:

FragmentManager manager = getSupportFragmentManager(); 
Fragment fragment = manager.findFragmentByTag("YourFragmentName"); 

if(fragment == null) 
    fragment = new YourFragment(); 

FragmentTransaction fragmentTransaction = manager.beginTransaction(); 
fragmentTransaction.replace(Your_Fragmnet_Container_Layout_id, fragment, fragment.getClass().getSimpleName()); 
fragmentTransaction.commit;