ncapdevi / FragNav

An Android library for managing multiple stacks of fragments
1.5k stars 220 forks source link

NPE Fragment.mNextAnim #35

Closed alashow closed 7 years ago

alashow commented 7 years ago

After upgrading to 1.2.4 version from 1.0.3, I get exceptions in my app sometimes when the application started from the background (minimized, then opened after some time):

java.lang.RuntimeException: Unable to start activity ComponentInfo{my.app.debug/my.app.ui.activity.MainActivity}: java.lang.NullPointerException: Attempt to write to field 'int android.support.v4.app.Fragment.mNextAnim' on a null object reference
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
    at android.app.ActivityThread.-wrap12(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6119)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.NullPointerException: Attempt to write to field 'int android.support.v4.app.Fragment.mNextAnim' on a null object reference
    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:770)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682)
    at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:594)
    at com.ncapdevi.fragnav.FragNavController.executePendingTransactions(FragNavController.java:498)
    at com.ncapdevi.fragnav.FragNavController.clearFragmentManager(FragNavController.java:514)
    at com.ncapdevi.fragnav.FragNavController.initialize(FragNavController.java:387)
    at com.ncapdevi.fragnav.FragNavController.<init>(FragNavController.java:120)
    at my.app.ui.activity.MainActivity.initFragments(MainActivity.java:203)
    at my.app.ui.activity.MainActivity.initViews(MainActivity.java:139)
    at my.app.ui.activity.MainActivity.init(MainActivity.java:130)
    at my.app.ui.activity.MainActivity.onCreate(MainActivity.java:97)
    at android.app.Activity.performCreate(Activity.java:6679)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
... 9 more

http://stackoverflow.com/questions/22489703/trying-to-remove-fragment-from-view-gives-me-nullpointerexception-on-mnextanim

My initialization of FragNavController:

mNavController = new FragNavController(savedInstanceState, getSupportFragmentManager(), R.id.container, fragments, FragNavController.TAB1);

Thank you!

ncapdevi commented 7 years ago

Could you update to 1.2.4 and see if you're still experiencing the issue?

alashow commented 7 years ago

Uh, sorry, my bad. I am using 1.2.4. Updated comment.

ncapdevi commented 7 years ago

Got it. Should be a fairly easy fix. I should be able to post a fix in the next couple of days.

alashow commented 7 years ago

Great! Thanks!

Offtopic: Do you suggest using Fragment getRootFragment(int index) over giving a list of fragments on initialization?

ncapdevi commented 7 years ago

There's no inherent performance advantage to using one over the other. Using getRootFragment performs lazy initialization of the object vs creating them all at once when you first initialize FragNav, so technically those are different, but the difference in minimal. Really it's about three things:

  1. If you don't know what the root fragments for each tab will be on creation, (i.e., until you actually click on it, you may not know what it's going to be) then you need getRootFragment.
  2. Overriding. If you have a base class that's implementing RootFragmentListener, there's some cases where it's nice for the base class to handle a couple of tabs, and then the subclasses handle indexes that are unique to them.
  3. Preference. No real reason behind this one, but to me having a function returning what the fragments are seems a bit clearer/cleaner. I can totally see the opposite argument being made and that having a list being made at construction being a bit clearer. So whichever makes the most sense to you, I wanted to have both.

(Theoretically there's a 4th point, which is that if for some reason that rootFragment is lost, it can still call that function and get a newInstance of the fragment. This was handled in the earlier days as a safety precaution, but in reality, if the library is well built, should never have to happen.)

ncapdevi commented 7 years ago

I am pushing out a fix right now for 1.2.5. I am not 100% sure that it will fix the issue, because I am surprised it is happening the way it is now. Give it a shot and if you continue to see it, let me know.

alashow commented 7 years ago

Thank you for the response.

I will try it.

rshah commented 7 years ago

I experienced this bug too. Now using 1.2.5 hope no crash anymore. Thank you for the fix