android - 没有迹象表明 NPE 可能发生在哪里

标签 android android-fragments nullpointerexception android-viewpager fragmentmanager

这是我作为错误得到的堆栈跟踪:

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)

我将解释我是如何得到这个错误的。 在我的 fragment 中,我调用了这个方法,然后它将通过我的 Activity 并启动另一个包含 viewpager 的 fragment 。

@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);
}

上面的方法将触发这个 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();
        }
    }
}

这是执行所有事务的 Activity 。

    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;
    }
}

这是 ShopFragmentviewpager:

    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);
    }
}

所以导致这个错误的场景如下: 我调用 sendActionToActivity(ACTION_ORDER, mShop);,现在我在 ShopFragment 中。当我在那里时,我可以看到带有一个项目的工具栏,当我点击它时会在我的 Activity 中调用这个方法:

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;

那就是错误发生的时候。如果我执行此方案但未调用 sendActionToActivity(ACTION_ORDER, mShop);,则一切正常。

最佳答案

以防其他人遇到此问题,我已将我的 FragmentStatePagerAdapter 更改为 FragmentPagerAdapter,它成功了。但是,如果您想使用 FragmentStatePagerAdapter,可能会修复此 link ,人们遇到了这个问题。

关于android - 没有迹象表明 NPE 可能发生在哪里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42213051/

相关文章:

java - NullPointerException 使用 ImageIO.read

android - 如何从 Android AlarmManager 回调执行网络 Activity

java - android - 如何从对象设置文本

java - OSNotificationPayload 无法转换为 JSONObject

java - Selenium POM 和 TestNG NullPointer 异常

java - 什么是NullPointerException,我该如何解决?

android - 如何在过滤 ListView 时禁用搜索文本弹出窗口?

android - getChildFragmentManager() 和支持库

android - 切换 fragment 时 OKHttp 崩溃

Android fragment 不保存状态