0

Ceci est la pile trace que je reçois comme une erreur:Aucune indication quant à l'endroit où NPE pourrait se produire

Process: com.peems.itcrowd, PID: 2949 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:873) at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:215) at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1481) at android.view.View.dispatchRestoreInstanceState(View.java:15751) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3231) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3237) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3237) at android.view.View.restoreHierarchyState(View.java:15729) at android.support.v4.app.Fragment.restoreViewState(Fragment.java:475) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1329) at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595) at android.support.v4.app.BackStackRecord.executePopOps(BackStackRecord.java:803) at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2353) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2146) at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2098) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2008) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:710) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) 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)

Je vais vous expliquer comment je reçois cette erreur. Dans mon fragment, j'appelle cette méthode qui va ensuite passer par mon activité et déclencher un autre fragment qui contient un viewpager.

@Override 
public void checkoutCartResult(Result<Shop> result) { 
    mShop = result.getData(); 
    sendActionToActivity(ACTION_ORDER, mShop); 
    DisplayUtil.doToast(getContext(), getString(R.string.checkout_successful)); 
} 

private void sendActionToActivity(String action, Shop shop) { 
    if (mListener == null) { 
     return; 
    } 
    Bundle bundle = new Bundle(); 
    bundle.putString(Constants.ACTION_KEY, action); 
    bundle.putParcelable(Constants.DATA_KEY_1, Parcels.wrap(shop)); 
    mListener.onFragmentInteraction(bundle); 
} 

La méthode ci-dessus le feu jusqu'à ce fragment:

public class ShopFragment extends BaseFragment implements ShopView, 
     ViewPager.OnPageChangeListener { 

    private static final String TAG = ShopFragment.class.getName(); 
    private static final String ARG_PARAM1 = "param1"; 

    FragmentShopBinding mBinder; 
    Shop mShop; 
    ShopPresenter mPresenter; 
    ShopAdapter mAdapter; 
    PreferenceAdapter mPreferenceAdapter; 
    LayerDrawable mCartMenuIcon; 
    List<String> mTabTitles; 
    String mImagePath; 
    boolean isProductsShown = false; 

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

    public static ShopFragment newInstance(Shop shop) { 
     ShopFragment fragment = new ShopFragment(); 
     Bundle args = new Bundle(); 
     args.putParcelable(ARG_PARAM1, Parcels.wrap(shop)); 
     fragment.setArguments(args); 
     return fragment; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setHasOptionsMenu(true); 
     if (getArguments() != null) { 
      Parcelable parcelable; 
      parcelable = getArguments().getParcelable(ARG_PARAM1); 
      mShop = Parcels.unwrap(parcelable); 
     } 
     mTabTitles = new ArrayList<>(4); 
     mTabTitles.add(getString(R.string.wishlist_fragment)); 
     mTabTitles.add(getString(R.string.history_fragment)); 
     mTabTitles.add(getString(R.string.offers_fragment)); 
     mTabTitles.add(getString(R.string.products_fragment)); 

    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     mBinder = DataBindingUtil.inflate(inflater, R.layout.fragment_shop, container, false); 
     mBinder.tabs.setTabMode(TabLayout.MODE_FIXED); 
     mBinder.tabs.setTabGravity(TabLayout.GRAVITY_FILL); 
     mAdapter = new ShopAdapter(getChildFragmentManager(), mTabTitles, mShop); 
     mPreferenceAdapter = new PreferenceAdapter(getContext()); 
     mBinder.viewpager.setAdapter(mAdapter); 
     mBinder.viewpager.addOnPageChangeListener(this); 
     checkForImage(); 
     mBinder.tabs.setupWithViewPager(mBinder.viewpager); 
     mPresenter = new ShopPresenterImpl(this); 
     ((MainActivity) getActivity()).setActionBarTitle(mShop.getName()); 
     EventBus.getDefault().register(this); 
     return mBinder.getRoot(); 
    } 

    @Override 
    public void onDestroyView() { 
     super.onDestroyView(); 
     EventBus.getDefault().unregister(this); 
    } 

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     //show cart items in badge 
     mCartMenuIcon = (LayerDrawable) menu.findItem(R.id.action_cart).getIcon(); 
     setBadgeCount(mCartMenuIcon, String.valueOf(mShop.getCartItems())); 

     // show/hide login icon 
     if (mShop.getLoginId() == -1) { 
      menu.findItem(R.id.action_login).setVisible(true); 
      menu.findItem(R.id.action_logout).setVisible(false); 
     } else { 
      menu.findItem(R.id.action_login).setVisible(false); 
      menu.findItem(R.id.action_logout).setVisible(true); 
     } 
     super.onCreateOptionsMenu(menu, inflater); 
    } 

    @Override 
    protected void setTypeface() { 

    } 

    @Override 
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
     DisplayUtil.hideKeyboard(ShopFragment.this.getActivity()); 
    } 

    @Override 
    public void onPageSelected(int position) { 
     String pageTitle; 
     pageTitle = mAdapter.getPageTitle(position).toString(); 
     isProductsShown = pageTitle.equals(getString(R.string.products_fragment)); 
     ShopFragment.this.getActivity().invalidateOptionsMenu(); 
     //reloadData(position); 
    } 

    @Override 
    public void onPageScrollStateChanged(int state) { 

    } 

    @Override 
    public void logoutShop(Shop shop) { 

    } 

    @Override 
    public void showError(Error error) { 
     DisplayUtil.okDialog(getContext(), error.getErrorTitle(), error.getErrorMessage(), new DialogInterface.OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialog, int which) { 
       dialog.dismiss(); 
      } 
     }); 
    } 

    @Override 
    public void showProgress(boolean show) { 

    } 

    private void sendActionToActivity(String action) { 
     if (mListener == null) { 
      return; 
     } 
     Bundle bundle = new Bundle(); 
     bundle.putString(Constants.ACTION_KEY, action); 
     mListener.onFragmentInteraction(bundle); 
    } 

    private void logoutShop() { 
     AsyncExecutor.create().execute(new AsyncExecutor.RunnableEx() { 
      @Override 
      public void run() throws Exception { 
       mPresenter.logoutShop(mShop); 
       ShopRepository shopRepository; 
       shopRepository = new ShopRepository(); 
       mShop.setLoginId(-1); 
       mShop.setCustomerId(-1); 
       mShop.setCartNumber(0); 
       mShop.setLineNumber(0); 
       mShop.setCartItems(0); 
       shopRepository.updateLoginNumber(mShop); 
       shopRepository.updateCart(mShop); 
       notifyChanges(); 
      } 
     }); 
    } 

    public void logoutDialog() { 
     DisplayUtil.logoutDialog(getContext(), getString(R.string.action_log_out), getString(R.string.are_you_sure), 
       new DialogInterface.OnClickListener() { 
        @Override 
        public void onClick(DialogInterface dialog, int which) { 
         logoutShop(); 
        } 
       }, new DialogInterface.OnClickListener() { 
        @Override 
        public void onClick(DialogInterface dialog, int which) { 
         dialog.dismiss(); 
        } 
       }); 
    } 

    private void setBadgeCount(LayerDrawable icon, String count) { 
     BadgeDrawable badge; 
     // Reuse drawable if possible 
     Drawable reuse = icon.findDrawableByLayerId(R.id.ic_badge); 
     if (reuse != null && reuse instanceof BadgeDrawable) { 
      badge = (BadgeDrawable) reuse; 
     } else { 
      badge = new BadgeDrawable(getContext()); 
     } 
     badge.setCount(count); 
     icon.mutate(); 
     icon.setDrawableByLayerId(R.id.ic_badge, badge); 
    } 

    private void notifyChanges() { 
     AuthShopResult event; 
     event = new AuthShopResult(); 
     event.setShop(mShop); 
     EventBus.getDefault().post(event); 
    } 

    private void checkForImage() { 
     mImagePath = mPreferenceAdapter.readImagePathMax(); 
     if (mImagePath.equals("")) { 
      mBinder.viewpager.setOffscreenPageLimit(4); 
     } 
    } 

    @Subscribe(threadMode = ThreadMode.MAIN) 
    public void onMessage(LoadCartNumber event) { 
     mShop = event.getShop(); 
    } 

    @Subscribe(threadMode = ThreadMode.MAIN) 
    public void onMessage(AuthShopResult event) { 
     mShop = event.getShop(); 
     // hide Login option menu 
     if (getActivity() != null) { 
      getActivity().invalidateOptionsMenu(); 
     } 
    } 
} 

Ceci est l'activité qui fait toutes les transactions.

public class MainActivity extends AppCompatActivity implements 
     BaseFragment.OnFragmentInteractionListener, 
     BaseDialogFragment.OnFragmentInteractionListener, 
     FragmentManager.OnBackStackChangedListener { 

    private static final String CURRENT_FRAGMENT = "current_fragment"; 
    private static final String CURRENT_PEEM_ID = "current_peem_id"; 
    private static final String CURRENT_SHOP_ID = "current_shop_id"; 
    private static final String CURRENT_CART_NUMBER = "current_cart_number"; 
    private static final String CURRENT_CART_LINE = "current_cart_line"; 
    private static final String CURRENT_CART_ITEMS = "current_cart_items"; 

    public ActivityMainBinding mBinder; 
    private Peem mCurrentPeem; 
    private Shop mCurrentShop; 
    private Fragment mFragment; 
    private DialogFragment mDialogFragment; 
    private PreferenceAdapter mPreferenceAdapter; 
    private int mFragmentBackStackCounter = 0; 
    private int languagePosition; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     //LeakCanary.install(getApplication()); 
     mBinder = DataBindingUtil.setContentView(this, R.layout.activity_main); 
     setSupportActionBar(mBinder.toolbar); 
     showActionBar(true); 
     mPreferenceAdapter = new PreferenceAdapter(App.getContext()); 
     getSupportFragmentManager().addOnBackStackChangedListener(MainActivity.this); 
    } 

    @Override 
    protected void onPostCreate(@Nullable Bundle savedInstanceState) { 
     super.onPostCreate(savedInstanceState); 
     EventBus.getDefault().register(this); 
     if (savedInstanceState != null) { 
      mFragment = getSupportFragmentManager().getFragment(savedInstanceState, CURRENT_FRAGMENT); 
      PeemRepository peemRepository = new PeemRepository(); 
      ShopRepository shopRepository = new ShopRepository(); 
      try { 
       Peem peem; 
       int peemId = savedInstanceState.getInt(CURRENT_PEEM_ID); 
       peem = peemRepository.findById(peemId); 
       mCurrentPeem = peem; 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      } 
      try { 
       Shop shop; 
       int shopId = savedInstanceState.getInt(CURRENT_SHOP_ID); 
       shop = shopRepository.findById(shopId); 
       mCurrentShop = shop; 
       if (mCurrentShop != null && mCurrentShop.getLoginId() == -1) { 
        mCurrentShop.setCartNumber(savedInstanceState.getInt(CURRENT_CART_NUMBER)); 
        mCurrentShop.setLineNumber(savedInstanceState.getInt(CURRENT_CART_LINE)); 
        mCurrentShop.setCartItems(savedInstanceState.getInt(CURRENT_CART_ITEMS)); 
       } 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      } 
     } else { 
      if (isUserLoggedIn()) { 
       checkFavourite(); 
      } else { 
       fragmentManager(RegisterFragment.newInstance()); 
      } 
     } 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     if (getCurrentFragment() == null) { 
      getSupportFragmentManager().putFragment(outState, CURRENT_FRAGMENT, mFragment); 
     } else { 
      mFragment = getCurrentFragment(); 
      getSupportFragmentManager().putFragment(outState, CURRENT_FRAGMENT, mFragment); 
     } 

     if (mCurrentPeem != null) { 
      int peemId = mCurrentPeem.getId(); 
      outState.putInt(CURRENT_PEEM_ID, peemId); 
     } 
     if (mCurrentShop != null) { 
      int shopId = mCurrentShop.getId(); 
      int cartNumber = mCurrentShop.getCartNumber(); 
      int cartLineNumber = mCurrentShop.getLineNumber(); 
      int cartItems = mCurrentShop.getCartItems(); 
      outState.putInt(CURRENT_SHOP_ID, shopId); 
      outState.putInt(CURRENT_CART_NUMBER, cartNumber); 
      outState.putInt(CURRENT_CART_LINE, cartLineNumber); 
      outState.putInt(CURRENT_CART_ITEMS, cartItems); 
     } 
     super.onSaveInstanceState(outState); 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     getSupportFragmentManager().removeOnBackStackChangedListener(com.peems.itcrowd.ui.activity.MainActivity.this); 
     EventBus.getDefault().unregister(this); 
     mFragment = null; 
     mDialogFragment = null; 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     MenuInflater inflater = getMenuInflater(); 
     inflater.inflate(R.menu.menu_ab, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.action_back_to_peem: 
       mFragment = PeemFragment.newInstance(); 
       getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 
       getSupportFragmentManager() 
         .beginTransaction() 
         .replace(R.id.fragment_holder, mFragment, Integer.toString(getFragmentCount())) 
         .addToBackStack(null) 
         .commit(); 
       return true; 
      case R.id.action_back_to_shop: 
       mFragment = ShopListFragment.newInstance(mCurrentPeem); 
       getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 
       getSupportFragmentManager() 
         .beginTransaction() 
         .replace(R.id.fragment_holder, mFragment, Integer.toString(getFragmentCount())) 
         .addToBackStack(null) 
         .commit(); 
       return true; 
      default: 
       // If we got here, the user's action was not recognized. 
       // Invoke the superclass to handle it. 
       return super.onOptionsItemSelected(item); 
     } 
    } 

    @Override 
    public void onFragmentInteraction(Bundle arg) { 
     String action; 
     action = arg.getString(Constants.ACTION_KEY); 

     if (action.equals(OrderSummaryFragment.ACTION_ORDER)) { 
      Shop shop; 
      Parcelable parcelable; 
      parcelable = arg.getParcelable(Constants.DATA_KEY_1); 
      shop = Parcels.unwrap(parcelable); 
      fragmentManager(ShopFragment.newInstance(shop)); 
      return; 
     } 

     if (action.equals(OrderSummaryFragment.ACTION_HIDE_ACTION_BAR)) { 
      showActionBar(false); 
      return; 
     } 

     if (action.equals(OrderSummaryFragment.ACTION_SHOW_ACTION_BAR)) { 
      showActionBar(true); 
      return; 
     } 

    } 

    private void fragmentManager(Fragment fragment) { 

     if (fragment instanceof PeemFragment) { 
      mFragment = fragment; 
      getSupportFragmentManager() 
        .beginTransaction() 
        .replace(R.id.fragment_holder, fragment, Integer.toString(getFragmentCount())) 
        .addToBackStack(PeemFragment.class.getSimpleName()) 
        .commit(); 
      return; 
     } 

     if (fragment instanceof ShopFragment) { 
      mFragment = fragment; 
      getSupportFragmentManager() 
        .beginTransaction() 
        .replace(R.id.fragment_holder, fragment, Integer.toString(getFragmentCount())) 
        .addToBackStack(ShopFragment.class.getSimpleName()) 
        .commit(); 
      return; 
     } 

     if (fragment instanceof ShopListFragment) { 
      mFragment = fragment; 
      getSupportFragmentManager() 
        .beginTransaction() 
        .replace(R.id.fragment_holder, fragment, Integer.toString(getFragmentCount())) 
        .addToBackStack(ShopListFragment.class.getSimpleName()) 
        .commit(); 
      return; 
     } 

     if (fragment instanceof OrderSummaryFragment) { 
      mFragment = fragment; 
      getSupportFragmentManager() 
        .beginTransaction() 
        .replace(R.id.fragment_holder, fragment, Integer.toString(getFragmentCount())) 
        .addToBackStack(OrderSummaryFragment.class.getSimpleName()) 
        .commit(); 
      return; 
     } 
    } 

    protected int getFragmentCount() { 
     return getSupportFragmentManager().getBackStackEntryCount(); 
    } 

    private Fragment getFragmentAt(int index) { 
     return getFragmentCount() > 0 ? getSupportFragmentManager().findFragmentByTag(Integer.toString(index)) : null; 
    } 

    protected Fragment getCurrentFragment() { 
     return getFragmentAt(getFragmentCount() - 1); 
    } 

    @Override 
    public void onBackPressed() { 
     // still not defined behavior 
     if (mFragmentBackStackCounter > 0) { 
      getSupportFragmentManager().popBackStack(); 
     } else if (mFragmentBackStackCounter == 0) { 
      finish(); 
     } 
    } 

    @Override 
    public void onBackStackChanged() { 
     int entryCount = getSupportFragmentManager().getBackStackEntryCount() - 1; 
     mFragmentBackStackCounter = entryCount; 
     if (entryCount >= 0) { 
      FragmentManager.BackStackEntry backStackEntry; 
      backStackEntry = getSupportFragmentManager().getBackStackEntryAt(entryCount); 
      /*if(mFragmentBackStackCounter > entryCount){ 
       mFragment = getSupportFragmentManager().findFragmentByTag(backStackEntry.getName()); 
      }*/ 
      mFragmentBackStackCounter = entryCount; 
     } 
    } 

    private void showActionBar(boolean state) { 
     ActionBar actionBar; 
     actionBar = getSupportActionBar(); 
     /*if (actionBar != null) { 
      actionBar.setTitle("SHOP");*/ 
     if (state) { 
      if (actionBar != null) { 
       actionBar.show(); 
      } 
     } else { 
      if (actionBar != null) { 
       actionBar.hide(); 
      } 
     } 
    } 

    private boolean isUserLoggedIn() { 
     String accessToken; 
     boolean isLoggedIn = true; 
     accessToken = mPreferenceAdapter.readAccessToken(); 
     if (accessToken.isEmpty()) { 
      isLoggedIn = false; 
     } 

     return isLoggedIn; 
    } 
} 

C'est le viewpager pour le ShopFragment:

public class ShopAdapter extends FragmentStatePagerAdapter { 

    int mNumOfTabs; 
    private final List<String> mTabTitles; 
    Shop mShop; 

    public enum TAB { 
     WISHLIST(0), HISTORY(1), OFFERS(2), PRODUCTS(3); 

     int value; 

     TAB(int i) { 
      this.value = i; 
     } 

     public int getValue() { 
      return value; 
     } 
    } 

    public ShopAdapter(FragmentManager fm, List<String> tabTitles, Shop shop) { 
     super(fm); 
     this.mTabTitles = tabTitles; 
     this.mNumOfTabs = tabTitles.size(); 
     this.mShop = shop; 
    } 

    public void addTitle(String title) { 
     mTabTitles.add(title); 
    } 

    @Override 
    public Fragment getItem(int position) { 

     switch (position) { 
      case 0: 
       return WishlistTabFragment.newInstance(mShop); 
      case 1: 
       return HistoryTabFragment.newInstance(mShop); 
      case 2: 
       return OffersTabFragment.newInstance(mShop); 
      case 3: 
       return ProductsFragment.newInstance(mShop); 
      default: 
       return null; 
     } 
    } 

    @Override 
    public int getCount() { 
     return mNumOfTabs; 
    } 

    @Override 
    public CharSequence getPageTitle(int position) { 
     reloadData(position); 
     return mTabTitles.get(position); 
    } 

    @Override 
    public int getItemPosition(Object object) { 
     return super.getItemPosition(object); 
    } 

    private void reloadData(int position) { 
     RefreshResult result = new RefreshResult(); 
     result.setPageNumber(position); 
     EventBus.getDefault().post(result); 
    } 
} 

Ainsi, le scénario conduisant à cette erreur est la suivante: j'appelle sendActionToActivity(ACTION_ORDER, mShop); et je suis maintenant dans le ShopFragment. Tout en étant là, je peux voir la barre d'outils avec un élément qui, lorsque je clique invoque cette méthode dans mon activité:

case R.id.action_back_to_shop: 
       mFragment = ShopListFragment.newInstance(mCurrentPeem); 
       getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 
       getSupportFragmentManager() 
         .beginTransaction() 
         .replace(R.id.fragment_holder, mFragment, Integer.toString(getFragmentCount())) 
         .addToBackStack(null) 
         .commit(); 
       return true; 

Et c'est lorsque l'erreur se produit. Si je fais ce scénario mais sans appeler sendActionToActivity(ACTION_ORDER, mShop); alors tout fonctionne bien.

+0

Vous vous plantez lors de la restauration de l'état d'instance enregistré de votre 'ViewPager'. La méthode 'onSaveInstanceState()' de votre activité est plutôt étrange, en particulier vos appels à 'putFragment()'. Et, vous utilisez des fragments imbriqués, qui sont à mon avis sujettes aux erreurs. Mais, d'une manière ou d'une autre, votre 'FragmentStatePagerAdapter' pense qu'il devrait y avoir des fragments, mais il n'y en a aucun pour l'instant, et je ne suis pas sûr de la façon dont vous vous placez dans cette position. – CommonsWare

+0

@CommonsWare Hmm avez-vous des suggestions? Parce que je n'ai vraiment aucune idée de comment le résoudre. – JackW5808

+0

Malheureusement, c'est assez un "mur de code" que je n'ai pas de bonnes recommandations. – CommonsWare

Répondre

2

Dans le cas où quelqu'un d'autre a ce problème, j'ai changé mon FragmentStatePagerAdapter à FragmentPagerAdapter et il a fait l'affaire. Mais dans le cas où vous voulez utiliser FragmentStatePagerAdapter il y a des correctifs possibles sur ce link, où les gens ont eu ce problème.