菜单选项单击后打开活动时出错

时间:2013-09-22 14:39:29

标签: java android database eclipse uri

这些是我得到的错误。

09-23 04:24:04.712: E/AndroidRuntime(332): FATAL EXCEPTION: main
09-23 04:24:04.712: E/AndroidRuntime(332): java.lang.RuntimeException: Unable to resume activity {ph.cksc.edu.softeng.financialsecretary/ph.cksc.edu.softeng.financialsecretary.BudgetsEditor}: java.lang.NullPointerException
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2120)
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135)
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1668)
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.app.ActivityThread.access$1500(ActivityThread.java:117)
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.os.Handler.dispatchMessage(Handler.java:99)
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.os.Looper.loop(Looper.java:123)
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.app.ActivityThread.main(ActivityThread.java:3683)
09-23 04:24:04.712: E/AndroidRuntime(332):  at java.lang.reflect.Method.invokeNative(Native Method)
09-23 04:24:04.712: E/AndroidRuntime(332):  at java.lang.reflect.Method.invoke(Method.java:507)
09-23 04:24:04.712: E/AndroidRuntime(332):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
09-23 04:24:04.712: E/AndroidRuntime(332):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
09-23 04:24:04.712: E/AndroidRuntime(332):  at dalvik.system.NativeStart.main(Native Method)
09-23 04:24:04.712: E/AndroidRuntime(332): Caused by: java.lang.NullPointerException
09-23 04:24:04.712: E/AndroidRuntime(332):  at ph.cksc.edu.softeng.financialsecretary.BudgetsEditor.onResume(BudgetsEditor.java:141)
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1150)
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.app.Activity.performResume(Activity.java:3832)
09-23 04:24:04.712: E/AndroidRuntime(332):  at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2110)
09-23 04:24:04.712: E/AndroidRuntime(332):  ... 12 more

这是BudgetsEditor的代码:

public class BudgetsEditor extends Activity {
    private static final String TAG = "BudgetsEditor";

    private static final String[] PROJECTION = new String[] { Budgets._ID, // 0
            Budgets.TITLE, // 1
            Budgets.AMOUNT, // 2
            Budgets.ROLLOVER_FLAG, // 3
            Budgets.START_DATE // 4
    };
    /** The index of the budget column */
    private static final int PROJECTION_INDEX_TITLE = 1;
    private static final int PROJECTION_INDEX_AMOUNT = 2;
    private static final int PROJECTION_INDEX_ROLLOVER_FLAG = 3;
    private static final int PROJECTION_INDEX_START_DATE = 4;

    // Identifiers for our menu items.
    private static final int REVERT_ID = Menu.FIRST;
    private static final int DISCARD_ID = Menu.FIRST + 1;
    private static final int DELETE_ID = Menu.FIRST + 2;
    private static final int SAVE_ID = Menu.FIRST + 3;

    // The different distinct states the activity can be run in.
    private static final int STATE_EDIT = 0;
    private static final int STATE_INSERT = 1;

    private int mState;
    private Uri mUri;
    private Cursor mCursor;

    private EditText mTitle;
    private EditText mAmount;
    private ToggleButton mRollover;
    private DateControlSet mStartDate;

    private String mOriginalTitle;
    private float mOriginalAmount;
    private int mOriginalRollover;
    private long mOriginalStartDate;

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

        final Intent intent = getIntent();
        final String action = intent.getAction();
        if (Intent.ACTION_EDIT.equals(action)) {
            // Requested to edit: set that state, and the data being edited.
            mState = STATE_EDIT;
            mUri = intent.getData();
        } else if (Intent.ACTION_INSERT.equals(action)) {
            // Requested to insert: set that state, and create a new entry
            // in the container.
            mState = STATE_INSERT;
            mUri = getContentResolver().insert(intent.getData(), null);

            // If we were unable to create a new budget, then just finish
            // this activity. A RESULT_CANCELED will be sent back to the
            // original activity if they requested a result.
            if (mUri == null) {
                Log.e(TAG, "Failed to insert new budget into " + getIntent().getData());
                finish();
                return;
            }

            // The new entry was created, so assume all will end well and
            // set the result to be returned.
            setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
        } else {
            // Whoops, unknown action! Bail.
            Log.e(TAG, "Unknown action, exiting");
            finish();
            return;
        }

        setContentView(R.layout.budgetslist_editor);

        mTitle = (EditText) findViewById(R.id.budget_title);
        mAmount = (EditText) findViewById(R.id.budget_amount);
        mStartDate = new DateControlSet(this, R.id.budget_start_date, R.id.budget_start_time);

        mCursor = managedQuery(mUri, PROJECTION, null, null, null);

        // If an instance of this activity had previously stopped, we can
        // get the original text it started with.
        if (savedInstanceState != null) {
            mOriginalTitle = savedInstanceState.getString(BudgetsPage.Budgets.TITLE);
            mOriginalAmount = savedInstanceState.getFloat(BudgetsPage.Budgets.AMOUNT);
            mOriginalRollover = savedInstanceState.getInt(BudgetsPage.Budgets.ROLLOVER_FLAG);
            mOriginalStartDate = savedInstanceState.getLong(BudgetsPage.Budgets.START_DATE);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        // If we didn't have any trouble retrieving the data, it is now
        // time to get at the stuff.
        if (mCursor != null) {
            // Make sure we are at the one and only row in the cursor.
            mCursor.moveToFirst();

            // Modify our overall title depending on the mode we are running in.
            if (mState == STATE_EDIT) {
                setTitle(getText(R.string.title_edit));
            } else if (mState == STATE_INSERT) {
                setTitle(getText(R.string.title_create));
            }

            // This is a little tricky: we may be resumed after previously being
            // paused/stopped. We want to put the new text in the text view,
            // but leave the user where they were (retain the cursor position
            // etc). This version of setText does that for us.
            String title = mCursor.getString(PROJECTION_INDEX_TITLE);
            float amount = mCursor.getFloat(PROJECTION_INDEX_AMOUNT);
            int rollover = mCursor.getInt(PROJECTION_INDEX_ROLLOVER_FLAG);
            long startDate = mCursor.getLong(PROJECTION_INDEX_START_DATE);

            mTitle.setTextKeepState(title);
            mAmount.setText(String.valueOf(amount));
            mRollover.setChecked(rollover == 1);
            mStartDate.setDate(startDate);

            // If we hadn't previously retrieved the original text, do so
            // now. This allows the user to revert their changes.
            if (mOriginalTitle == null) {
                mOriginalTitle = title;
            }
            if (mOriginalAmount == 0) {
                mOriginalAmount = amount;
            }
            if (mOriginalRollover == 0) {
                mOriginalRollover = rollover;
            }
            if (mOriginalStartDate == 0) {
                mOriginalStartDate = startDate;
            }
        } else {
            setTitle(getText(R.string.error_title));
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // Save away the original text, so we still have it if the activity
        // needs to be killed while paused.
        outState.putString(BudgetsPage.Budgets.TITLE, mOriginalTitle);
        outState.putFloat(BudgetsPage.Budgets.AMOUNT, mOriginalAmount);
        outState.putInt(BudgetsPage.Budgets.ROLLOVER_FLAG, mOriginalRollover);
        outState.putLong(BudgetsPage.Budgets.START_DATE, mOriginalStartDate);
    }

    @Override
    protected void onPause() {
        super.onPause();

        // The user is going somewhere else, so make sure their current
        // changes are safely saved away in the provider. We don't need
        // to do this if only editing.
        if (mCursor != null) {
            final String title = mTitle.getText().toString();

            // If this activity is finished, and there is no text, then we
            // do something a little special: simply delete the budget entry.
            // Account that we do this both for editing and inserting... it
            // would be reasonable to only do it when inserting.
            if (isFinishing() && TextUtils.isEmpty(title)) {
                setResult(RESULT_CANCELED);
                deleteAccount();
            } else {
                saveAccount();
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        // Build the menus that are shown when editing.
        menu.add(0, SAVE_ID, 0, R.string.menu_save).setShortcut('0', 's').setIcon(android.R.drawable.ic_menu_save);
        if (mState == STATE_EDIT) {
            menu.add(0, REVERT_ID, 0, R.string.menu_revert).setShortcut('1', 'r')
                    .setIcon(android.R.drawable.ic_menu_revert);
            menu.add(0, DELETE_ID, 0, R.string.menu_delete).setShortcut('2', 'd')
                    .setIcon(android.R.drawable.ic_menu_delete);

            // Build the menus that are shown when inserting.
        } else {
            menu.add(0, DISCARD_ID, 0, R.string.menu_discard).setShortcut('1', 'd')
                    .setIcon(android.R.drawable.ic_menu_delete);
        }

        // If we are working on a full budget, then append to the
        // menu items for any other activities that can do stuff with it
        // as well. This does a query on the system for any activities that
        // implement the ALTERNATIVE_ACTION for our data, adding a menu item
        // for each one that is found.
        Intent intent = new Intent(null, getIntent().getData());
        intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
        menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, new ComponentName(this, BudgetsEditor.class), null,
                intent, 0, null);

        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        final String title = mTitle.getText().toString();
        menu.findItem(SAVE_ID).setEnabled(isAccountChanged() && !TextUtils.isEmpty(title));
        if (mState == STATE_EDIT) {
            menu.findItem(REVERT_ID).setEnabled(isAccountChanged());
        }
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle all of the possible menu actions.
        switch (item.getItemId()) {
        case DELETE_ID:
            deleteAccount();
            finish();
            break;
        case DISCARD_ID:
            cancelAccount();
            setResult(RESULT_CANCELED);
            finish();
            break;
        case REVERT_ID:
            cancelAccount();
            setResult(RESULT_CANCELED);
            finish();
            break;
        case SAVE_ID:
            saveAccount();
            finish();
            break;
        }
        return super.onOptionsItemSelected(item);
    }

    private boolean isAccountChanged() {
        final float amount = getNewAccountAmount();
        final String title = mTitle.getText().toString();
        final int rollover = mRollover.isChecked() ? 1 : 0;
        final long startDate = mStartDate.getDate().getTime();
        return !title.equals(mOriginalTitle) || amount != mOriginalAmount || rollover != mOriginalRollover
                || startDate != mOriginalStartDate;
    }

    private float getNewAccountAmount() {
        float amount;
        try {
            amount = Float.parseFloat(mAmount.getText().toString());
        } catch (Exception e) {
            amount = 0;
        }
        return amount;
    }

    /**
     * Take care of canceling work on a budget. Deletes the budget if we had created it, otherwise reverts to the
     * original text.
     */
    private final void cancelAccount() {
        if (mCursor != null) {
            if (mState == STATE_EDIT) {
                // Put the original budget text back into the database
                mCursor.close();
                mCursor = null;
                if (isAccountChanged()) {
                    ContentValues values = new ContentValues();
                    values.put(Budgets.TITLE, mOriginalTitle);
                    values.put(Budgets.AMOUNT, mOriginalAmount);
                    values.put(Budgets.ROLLOVER_FLAG, mOriginalRollover);
                    values.put(Budgets.START_DATE, mOriginalStartDate);
                    getContentResolver().update(mUri, values, null, null);
                }
            } else if (mState == STATE_INSERT) {
                // We inserted an empty budget, make sure to delete it
                deleteAccount();
            }
        }
    }

    private void saveAccount() {
        final float amount = getNewAccountAmount();
        ContentValues values = new ContentValues();
        values.put(Budgets.TITLE, mTitle.getText().toString());
        values.put(Budgets.AMOUNT, amount);
        values.put(Budgets.ROLLOVER_FLAG, mRollover.isChecked() ? 1 : 0);
        values.put(Budgets.START_DATE, mStartDate.getDate().getTime());
        getContentResolver().update(mUri, values, null, null);
    }

    /**
     * Take care of deleting a budget. Simply deletes the entry.
     */
    private final void deleteAccount() {
        if (mCursor != null) {
            mCursor.close();
            mCursor = null;

            getContentResolver().delete(mUri, null, null);

            mTitle.setText("");
        }
    }
}

1 个答案:

答案 0 :(得分:0)

看起来你没有通过findViewById在Oncreate()中设置mRollover的值, 因此,当它在onResume中引用时,它始终为null。因此NullPointerException。