简体   繁体   中英

nullpointerexception using fragmentstatepageradapter

i am having an issue with an app i am making, everything seemed to be working ok until i started getting an error seemingly out of no where i dont believe i changed any thing from when it was working but every time i open the activity it give me a NullPointerException, heres the logcat from it.

09-13 18:29:54.951: E/AndroidRuntime(4407): FATAL EXCEPTION: main
09-13 18:29:54.951: E/AndroidRuntime(4407): Process: renseew.knowyourtime, PID: 4407
09-13 18:29:54.951: E/AndroidRuntime(4407): java.lang.NullPointerException
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.support.v13.app.FragmentCompatICS.setMenuVisibility(FragmentCompatICS.java:23)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.support.v13.app.FragmentCompat$ICSFragmentCompatImpl.setMenuVisibility(FragmentCompat.java:41)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.support.v13.app.FragmentCompat.setMenuVisibility(FragmentCompat.java:68)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.support.v13.app.FragmentStatePagerAdapter.instantiateItem(FragmentStatePagerAdapter.java:120)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:837)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.support.v4.view.ViewPager.populate(ViewPager.java:987)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.support.v4.view.ViewPager.populate(ViewPager.java:919)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1441)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.View.measure(View.java:16497)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:762)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.View.measure(View.java:16497)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.View.measure(View.java:16497)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:327)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.View.measure(View.java:16497)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2291)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.View.measure(View.java:16497)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1916)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1113)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1295)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.Choreographer.doCallbacks(Choreographer.java:574)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.Choreographer.doFrame(Choreographer.java:544)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.os.Handler.handleCallback(Handler.java:733)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.os.Handler.dispatchMessage(Handler.java:95)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.os.Looper.loop(Looper.java:136)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at android.app.ActivityThread.main(ActivityThread.java:5017)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at java.lang.reflect.Method.invokeNative(Native Method)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at java.lang.reflect.Method.invoke(Method.java:515)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
09-13 18:29:54.951: E/AndroidRuntime(4407):     at dalvik.system.NativeStart.main(Native Method)

the activity uses a FragmentStatePagerAdapter to dynamically add tabs from a fragment to to activity, ive also tried changing if(position < companies.size() -1) to if(position < companies.size()) no change(the first one worked before i started getting the error) heres the activity code.

public class UserDetails extends BaseActivity implements ActionBar.TabListener {

    CompanyPagerAdapter companyPagerAdapter;
    ViewPager viewPager;
    Cursor cursor;

    SettingsDBAdapter settingsDBAdapter;
    String companyName;
    private List<String> companies = new ArrayList<String>();
    ActionBar ab;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_details);
        updateActionBarNavigation();
        initialize();
        setupTabs();
        getCompanies();
        getTabs();
    }

    private void initialize() {
        if(ab != null)
            ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        viewPager = (ViewPager) findViewById(R.id.UDviewpager);

        ContentResolver settingsContent = this.getContentResolver();
        cursor = settingsContent.query(KnowYourTimeContentProvider.CONTENT_URI_SETTINGS, null, null, null, null);
        settingsDBAdapter = new SettingsDBAdapter(getApplicationContext());

        if (cursor.getCount() == 0) {
            settingsDBAdapter.settingsDBOpen();
            settingsDBAdapter.setDefaultSettings();
        }
    }

    private void setupTabs() {
        companyPagerAdapter = new CompanyPagerAdapter(getFragmentManager());

        viewPager.setAdapter(companyPagerAdapter);
        viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) {
                        if (ab != null) {
                            ab.setSelectedNavigationItem(position);
                        }
                    }
                });
    }

    private void getTabs() {
        for (int i = 0; i < companyPagerAdapter.getCount(); i++) {
            if (ab != null) {
                ab.addTab(ab.newTab()
                        .setText(companyPagerAdapter.getPageTitle(i))
                        .setTabListener(this));
            }
        }
    }

    private void getCompanies() {
        cursor = settingsDBAdapter.getCompanies();
        if (companies.size() != 0) {
            for (int i = 0; i < companies.size(); i++) {
                companyName = companies.get(i);
                companies.add(companyName);
            }
        } else if (cursor.getCount() != 0) {
            while (cursor.moveToNext()) {
                companyName = cursor.getString(cursor.getColumnIndex("company"));
                companies.add(companyName);
            }
        } else {
            companyName = getString(R.string.company);
            companies.add(companyName);
        }
        companyPagerAdapter.notifyDataSetChanged();
    }

    @Override
    protected void onNavDrawerStateChanged(boolean isOpen, boolean isAnimating) {
        super.onNavDrawerStateChanged(isOpen, isAnimating);
        updateActionBarNavigation();
    }

    @Override
    protected void onActionBarAutoShowOrHide(boolean shown) {
        super.onActionBarAutoShowOrHide(shown);
    }

    private void updateActionBarNavigation() {
        boolean show = !isNavDrawerOpen();

        ab = getActionBar();
        if (show && ab != null) {
            ab.setDisplayShowCustomEnabled(true);
            ab.setDisplayShowTitleEnabled(true);
            ab.setDisplayUseLogoEnabled(false);
            ab.setTitle(getString(R.string.title_user_details));
        } else if (ab != null) {
            ab.setDisplayShowCustomEnabled(false);
            ab.setDisplayShowTitleEnabled(false);
            ab.setDisplayUseLogoEnabled(true);
        }
    }

    @Override
    protected int getSelfNavDrawerItem() {
        return NAVDRAWER_ITEM_USERDETAILS;
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab,
                              FragmentTransaction fragmentTransaction) {
        viewPager.setCurrentItem(tab.getPosition());

        companies.get(tab.getPosition());
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab,
                                FragmentTransaction fragmentTransaction) {
    }

    @Override
    public void onTabReselected(ActionBar.Tab tab,
                                FragmentTransaction fragmentTransaction) {
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.usersettings_menu, menu);
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.clear();
        menu.add(Menu.NONE, R.id.addCompany, Menu.NONE, getString(R.string.add) + " " + getString(R.string.company));
        menu.add(Menu.NONE, R.id.removeCompany, Menu.NONE, getString(R.string.subtract) + " " + getString(R.string.company));
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem menuItem) {
        switch (menuItem.getItemId()) {
            case R.id.addCompany:
                companies.clear();
                companyName = getString(R.string.company);
                companies.add(companyName);
                companyPagerAdapter.notifyDataSetChanged();
                getTabs();
                return true;
            case R.id.removeCompany:
                return true;
            default:
                return super.onOptionsItemSelected(menuItem);
        }
    }

    public class CompanyPagerAdapter extends FragmentStatePagerAdapter {

        public CompanyPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            while (position < companies.size() - 1) {
                if (position < companies.size() - 1) {
                    position++;
                    return FragmentUserDetails.newInstance(companies.get(position));
                }
            }
            return null;
        }

        @Override
        public int getCount() {
            return companies.size();
        }

        @Override
        public CharSequence getPageTitle(int position) {
            while (position < companies.size() - 1) {
                if (position < companies.size() - 1) {
                    position++;
                    return companies.get(position);
                }
            }
            return "";
        }
    }
}

and here is the code for the fragment that the activity opens.

public class FragmentUserDetails extends Fragment implements AdapterView.OnItemClickListener, View.OnClickListener {

    private BaseAdapter listAdapter;
    private Cursor settingsCursor, companyCursor;

    private String payrate, payperiod, weekstart, allowances, maritalstatus;
    private String companyname;
    private Switch cbMaritalStatus;
    public EditText etCompanyName, etPayrate;
    private Spinner sPayPeriod, sPeriodStart, sAllowances;
    SettingsDBAdapter settingsDBAdapter;

    static FragmentUserDetails newInstance(String title) {
        FragmentUserDetails fragmentUserDetails = new FragmentUserDetails();
        Bundle args = new Bundle();
        args.putString("title", title);
        fragmentUserDetails.setArguments(args);
        return fragmentUserDetails;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_user_details, container, false);
        initialization(view);
        return view;
    }

    private void initialization(View view) {
        etCompanyName = (EditText) view.findViewById(R.id.UDedittextCompany);
        etPayrate = (EditText) view.findViewById(R.id.UDedittextPayrate);
        sPayPeriod = (Spinner) view.findViewById(R.id.UDspinnerPayPeriod);
        sPeriodStart = (Spinner) view.findViewById(R.id.UDspinnerPeriodStart);
        sAllowances = (Spinner) view.findViewById(R.id.UDspinnerAllowances);
        cbMaritalStatus = (Switch) view.findViewById(R.id.UDswitchMaritalStatus);
        Button save = (Button) view.findViewById(R.id.UDbuttonSaveSettings);

        save.setOnClickListener(this);

        ContentResolver settingsContent = getActivity().getContentResolver();
        settingsCursor = settingsContent.query(KnowYourTimeContentProvider.CONTENT_URI_SETTINGS, null, null, null, null);
        settingsDBAdapter = new SettingsDBAdapter(getActivity().getApplicationContext());

        companyname = getArguments().getString("title");

        if (settingsCursor.getCount() != 0) {
            while (settingsCursor.moveToNext()) {
                companyCursor = settingsDBAdapter.fetchCompanyInfo(companyname);
            }

            if (companyCursor.getCount() != 0) {
                while (companyCursor.moveToNext()) {
                    payrate = companyCursor.getString(companyCursor.getColumnIndex("payrate"));
                    payperiod = companyCursor.getString(companyCursor.getColumnIndex("payperiod"));
                    weekstart = companyCursor.getString(companyCursor.getColumnIndex("weekstart"));
                    allowances = companyCursor.getString(companyCursor.getColumnIndex("allowances"));
                    maritalstatus = companyCursor.getString(companyCursor.getColumnIndex("maritalstatus"));
                }
            } else {
                payrate = "";
                payperiod = getString(R.string.weekly);
                weekstart = getString(R.string.sunday);
                allowances = "0";
                maritalstatus = getString(R.string.no);
            }
        } else {
            companyname = getString(R.string.company);
        }

        etCompanyName.setText(companyname);
        etPayrate.setText(payrate);
        sPayPeriod.setSelection(getIndex(sPayPeriod, payperiod));
        sPeriodStart.setSelection(getIndex(sPeriodStart, weekstart));
        sAllowances.setSelection(getIndex(sAllowances, allowances));

        if (maritalstatus.equals(getString(R.string.yes))) {
            cbMaritalStatus.setChecked(true);
        } else {
            cbMaritalStatus.setChecked(false);
        }
    } 
}

sorry to put so much code im just unsure what is causing the issue. thanks in advance for any help

Update: so the error does seem to be coming from getItem() using the debugger. it runs through once just fine(which makes sense because there is 1 row initially) but the second time around is when it causes the crash. i also changed the code within it to this

public Fragment getItem(int position) {
    FragmentUserDetails fragment = null;
        if (position < companies.size() - 1) {
            fragment = FragmentUserDetails.newInstance(companies.get(position));
        }
    return fragment;
}

to make it simpler as suggested. still getting the same error. thanks again for any help

Your implementation of getItem() looks incredibly suspicious. This may or may not be related to your current error. Let's analyze your current code:

    public Fragment getItem(int position) {
        while (position < companies.size() - 1) {
            if (position < companies.size() - 1) {
                position++;
                return FragmentUserDetails.newInstance(companies.get(position));
            }
        }
        return null;
    }

In order to proceed with this analysis, we need to define the preconditions:

  1. companies contains 5 String s. The exact values are irrelevant.

  2. position is 0-based with a value of 2 .

In this particular situation, both the while and if conditions evaluate to true , so position is incremented and we immediately return the value of newInstance() .

This shows something very important: as long as the while condition is true , the if condition is also true and we will immediately return a value. This complete negates the need for a while loop at all.

Now that we see that this implementation is incorrect, let's back up and examine what we want to accomplish. The main idea is that we want to return a Fragment for the "company" at index position . A simplistic implementation is very simple:

    public Fragment getItem(int position) {
        return FragmentUserDetails.newInstance(companies.get(position));
    }

In theory, position should never be outside the range, but if you want to be safe, you can add an if statement for error checking:

    public Fragment getItem(int position) {
        if (0 <= position && position < companies.size()) {
            return FragmentUserDetails.newInstance(companies.get(position));
        }
    }

Now if you are still not getting the expected behavior, the error is somewhere else and we will need to analyze other sections of your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM