切换到横向时,为什么我的片段会崩溃?

时间:2014-01-10 21:17:45

标签: java android android-fragments orientation

更具体地说,我创建了一个创建帐户片段和一个登录片段。当切换到创建帐户片段中的横向时,它实际上返回到登录片段。然后,如果您尝试切换回肖像,那么应用程序崩溃。我看过类似的问题,但我无法从中得到任何结论。我非常感谢帮助人员!

CreateAccountFragment

package com.keyconsultant.parse.logintutorial;
/**
 * Create an Account. Username is the primary method of login. Email is used for forgotten password recovery. 
 * 
 * @author Trey Robinson
 *
 */
public class CreateAccountFragment extends BaseFragment implements OnClickListener {

    protected static final String EXTRA_EMAIL = "com.keyconsultant.parse.logintutorial.fragment.extra.EMAIL";
    protected static final String EXTRA_USERNAME = "com.keyconsultant.parse.logintutorial.fragment.extra.USERNAME";
    protected static final String EXTRA_PASSWORD = "com.keyconsultant.parse.logintutorial.fragment.extra.PASSWORD";
    protected static final String EXTRA_CONFIRM = "com.keyconsultant.parse.logintutorial.fragment.extra.CONFIRMPASSWORD";

    private EditText mUserNameEditText;
    private EditText mEmailEditText; 
    private EditText mPasswordEditText;
    private EditText mConfirmPasswordEditText;
    private Button mCreateAccountButton;

    private String mEmail;
    private String mUsername;
    private String mPassword;
    private String mConfirmPassword;

    /**
     * Factory method for creating fragment instances.
     * @return
     */
    public static CreateAccountFragment newInstance(){
        return new CreateAccountFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_create_account, container, false);

        mUserNameEditText = (EditText)view.findViewById(R.id.etUsername);
        mEmailEditText = (EditText)view.findViewById(R.id.etEmail);
        mPasswordEditText = (EditText)view.findViewById(R.id.etPassword);
        mConfirmPasswordEditText = (EditText)view.findViewById(R.id.etPasswordConfirm);

        mCreateAccountButton = (Button)view.findViewById(R.id.btnCreateAccount);
        mCreateAccountButton.setOnClickListener(this);
        return view;
    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        if(savedInstanceState != null){
            mEmailEditText.setText(savedInstanceState.getString(EXTRA_EMAIL));
            mUserNameEditText.setText(savedInstanceState.getString(EXTRA_USERNAME));
            mPasswordEditText.setText(savedInstanceState.getString(EXTRA_PASSWORD));
            mConfirmPasswordEditText.setText(savedInstanceState.getString(EXTRA_CONFIRM));
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(EXTRA_EMAIL, mEmailEditText.getText().toString());
        outState.putString(EXTRA_USERNAME, mUserNameEditText.getText().toString());
        outState.putString(EXTRA_PASSWORD, mPasswordEditText.getText().toString());
        outState.putString(EXTRA_CONFIRM, mConfirmPasswordEditText.getText().toString());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btnCreateAccount:
            createAccount();
            break;

        default:
            break;
        }
    }

    /**
     * Some front end validation is done that is not monitored by the service. 
     * If the form is complete then the information is passed to the service. 
     */
    private void createAccount(){
        clearErrors();

        boolean cancel = false;
        View focusView = null;

     // Store values at the time of the login attempt.
        mEmail = mEmailEditText.getText().toString();
        mUsername = mUserNameEditText.getText().toString();
        mPassword = mPasswordEditText.getText().toString();
        mConfirmPassword = mConfirmPasswordEditText.getText().toString();

        // Check for a valid confirm password.
        if (TextUtils.isEmpty(mConfirmPassword)) {
            mConfirmPasswordEditText.setError(getString(R.string.error_field_required));
            focusView = mConfirmPasswordEditText;
            cancel = true;
        } else if (mPassword != null && !mConfirmPassword.equals(mPassword)) {
            mPasswordEditText.setError(getString(R.string.error_invalid_confirm_password));
            focusView = mPasswordEditText;
            cancel = true;
        }
        // Check for a valid password.
        if (TextUtils.isEmpty(mPassword)) {
            mPasswordEditText.setError(getString(R.string.error_field_required));
            focusView = mPasswordEditText;
            cancel = true;
        } else if (mPassword.length() < 4) {
            mPasswordEditText.setError(getString(R.string.error_invalid_password));
            focusView = mPasswordEditText;
            cancel = true;
        }

        // Check for a valid email address.
        if (TextUtils.isEmpty(mEmail)) {
            mEmailEditText.setError(getString(R.string.error_field_required));
            focusView = mEmailEditText;
            cancel = true;
        } else if (!mEmail.contains("@")) {
            mEmailEditText.setError(getString(R.string.error_invalid_email));
            focusView = mEmailEditText;
            cancel = true;
        }

        if (cancel) {
            // There was an error; don't attempt login and focus the first
            // form field with an error.
            focusView.requestFocus();
        } else {
            // Show a progress spinner, and kick off a background task to
            // perform the user login attempt.
            UserManager.getInstance().signUp(mUsername.toLowerCase(Locale.getDefault()), mEmail, mPassword);

        }

    }

    /**
     * Remove error messages from all fields. 
     */
    private void clearErrors(){ mEmailEditText.setError(null);
        mUserNameEditText.setError(null);
        mPasswordEditText.setError(null);
        mConfirmPasswordEditText.setError(null);
    }

    @Subscribe
    public void onSignInError(AuthenticateUserErrorEvent event){
        clearErrors();
        switch (event.getErrorCode()) {
            case ParseException.INVALID_EMAIL_ADDRESS:
                mEmailEditText.setError(getString(R.string.error_invalid_email));
                mEmailEditText.requestFocus();
                break;
            case ParseException.EMAIL_TAKEN:
                mEmailEditText.setError(getString(R.string.error_duplicate_email));
                mEmailEditText.requestFocus();
                break;
            case ParseException.USERNAME_TAKEN:
                mUserNameEditText.setError(getString(R.string.error_duplicate_username));
                mUserNameEditText.requestFocus();
                break;
            default:
                UnknownErrorDialogFactory.createUnknownErrorDialog(this.getActivity()).show();
                break;
        }
    }

}

LoginFragment

package com.keyconsultant.parse.logintutorial;
/**
 * Fragment for logging in. Includes button for loading the Create account view.
 * 
 * @author Trey Robinson
 * 
 */
public class LoginFragment extends BaseFragment {

    public static final String EXTRA_USERNAME = "com.keyconsultant.parse.logintutorial.activity.extra.USERNAME";
    public static final String EXTRA_PASSWORD = "com.keyconsultant.parse.logintutorial.activity.extra.PASSWORD";

    // UI references.
    private EditText mUserNameEditText;
    private EditText mPasswordEditText;

    /**
     * Factory method for creating new fragments
     * 
     * @return
     */
    public static LoginFragment newInstance() {
        return new LoginFragment();
    }

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

        mUserNameEditText = (EditText) view.findViewById(R.id.username);

        mPasswordEditText = (EditText) view.findViewById(R.id.password);
        mPasswordEditText
                .setOnEditorActionListener(new TextView.OnEditorActionListener() {
                    @Override
                    public boolean onEditorAction(TextView textView, int id,
                            KeyEvent keyEvent) {
                        if (id == EditorInfo.IME_NULL) {
                            attemptLogin();
                            return true;
                        }
                        return false;
                    }
                });

        view.findViewById(R.id.sign_in_button).setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        attemptLogin();
                    }
                });

        view.findViewById(R.id.register_button).setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        createAccount();
                    }
                });

        view.findViewById(R.id.forgot_button).setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        forgotPassword();
                    }
                });
        return view;
    }

    /**
     * Open the forgotPassword dialog
     */
    private void forgotPassword() {
        FragmentManager fm = getActivity().getSupportFragmentManager();
        ForgotPasswordDialogFragment forgotPasswordDialog = new ForgotPasswordDialogFragment();
        forgotPasswordDialog.show(fm, null);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (savedInstanceState != null) {
            mUserNameEditText.setText(savedInstanceState
                    .getString(EXTRA_USERNAME));
            mPasswordEditText.setText(savedInstanceState
                    .getString(EXTRA_PASSWORD));
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(EXTRA_USERNAME, mUserNameEditText.getText()
                .toString());
        outState.putString(EXTRA_PASSWORD, mPasswordEditText.getText()
                .toString());
    }

    /**
     * Attempts to sign in or register the account specified by the login form.
     * If there are form errors (invalid email, missing fields, etc.), the
     * errors are presented and no actual login attempt is made.
     */
    public void attemptLogin() {

        clearErrors();

        // Store values at the time of the login attempt.
        String username = mUserNameEditText.getText().toString();
        String password = mPasswordEditText.getText().toString();

        boolean cancel = false;
        View focusView = null;

        // Check for a valid password.
        if (TextUtils.isEmpty(password)) {
            mPasswordEditText
                    .setError(getString(R.string.error_field_required));
            focusView = mPasswordEditText;
            cancel = true;
        } else if (password.length() < 4) {
            mPasswordEditText
                    .setError(getString(R.string.error_invalid_password));
            focusView = mPasswordEditText;
            cancel = true;
        }

        // Check for a valid email address.
        if (TextUtils.isEmpty(username)) {
            mUserNameEditText
                    .setError(getString(R.string.error_field_required));
            focusView = mUserNameEditText;
            cancel = true;
        }

        if (cancel) {
            // There was an error; don't attempt login and focus the first
            // form field with an error.
            focusView.requestFocus();
        } else {
            // perform the user login attempt.
            UserManager.getInstance().authenticate(
                    username.toLowerCase(Locale.getDefault()), password);
        }
    }

    /**
     * Load the create account view.
     */
    private void createAccount() {
        FragmentManager fragmentManager = getActivity()
                .getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager
                .beginTransaction();
        fragmentTransaction
                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        fragmentTransaction.replace(
                ((ViewGroup) getView().getParent()).getId(),
                CreateAccountFragment.newInstance());
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }

    /**
     * Remove all edit text errors
     */
    private void clearErrors() {
        mUserNameEditText.setError(null);
        mPasswordEditText.setError(null);
    }

    @Subscribe
    public void onSignInError(AuthenticateUserErrorEvent event) {
        clearErrors();
        switch (event.getErrorCode()) {
        case ParseException.OBJECT_NOT_FOUND:
            mPasswordEditText
                    .setError(getString(R.string.error_incorrect_password));
            mPasswordEditText.requestFocus();
            break;
        default:
            UnknownErrorDialogFactory.createUnknownErrorDialog(
                    this.getActivity()).show();
            break;
        }
    }
}

以防万一你需要它是我的LoginActivity

package com.keyconsultant.parse.logintutorial;

/**
 * Activity which displays a login screen to the user, offering registration as
 * well. Based loosley on the default Login template.
 * 
 * @author Trey Robinson
 */
public class LoginActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        Parse.initialize(this, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");


        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager
                .beginTransaction();
        fragmentTransaction
                .replace(R.id.main_view, LoginFragment.newInstance());
        fragmentTransaction.commit();
        parseCache();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.activity_login, menu);
        return true;

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
        case R.id.menu_forgot_password:
            forgotPassword();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    /**
     * Open the forgotPassword dialog
     */
    private void forgotPassword() {
        FragmentManager fm = getSupportFragmentManager();
        ForgotPasswordDialogFragment forgotPasswordDialog = new ForgotPasswordDialogFragment();
        forgotPasswordDialog.show(fm, null);
    }

    @Subscribe
    public void onSignInStart(AuthenticateUserStartEvent event) {
        showProgress(true, getString(R.string.login_progress_signing_in));
    }

    @Subscribe
    public void onSignInSuccess(AuthenticateUserSuccessEvent event) {
        showProgress(false, getString(R.string.login_progress_signing_in));
        Intent loginSuccess = new Intent(this, MainActivity.class);
        startActivity(loginSuccess);
        finish();
    }

    @Subscribe
    public void onSignInError(AuthenticateUserErrorEvent event) {
        showProgress(false, getString(R.string.login_progress_signing_in));
    }

    @Subscribe
    public void onForgotPasswordStart(UserForgotPasswordStartEvent event) {
        showProgress(true, getString(R.string.login_progress_signing_in));
    }

    @Subscribe
    public void onForgotPasswordSuccess(UserForgotPasswordSuccessEvent event) {
        showProgress(false, getString(R.string.login_progress_signing_in));
        Toast toast = Toast.makeText(this,
                "A password reset email has been sent.", Toast.LENGTH_LONG);
        toast.show();
    }

    @Subscribe
    public void onForgotPasswordError(UserForgotPasswordErrorEvent event) {
        showProgress(false, getString(R.string.login_progress_signing_in));
        Toast toast = Toast.makeText(this,
                "An error has occured. Please try again.", Toast.LENGTH_LONG);
        toast.show();
    }

    private void parseCache() {
        Intent intent;

        if (ParseUser.getCurrentUser() != null) {
            intent = new Intent(this, MainActivity.class);
            startActivity(intent);
            this.finish();
        }
    }
}

这是logcat

01-10 16:09:05.796: I/Process(1923): Sending signal. PID: 1923 SIG: 9
01-10 17:00:57.513: I/Choreographer(1975): Skipped 111 frames!  The application may be doing too much work on its main thread.
01-10 17:00:57.513: D/gralloc_goldfish(1975): Emulator without GPU emulation detected.
01-10 17:00:58.363: I/Choreographer(1975): Skipped 36 frames!  The application may be doing too much work on its main thread.
01-10 17:00:58.833: I/Choreographer(1975): Skipped 37 frames!  The application may be doing too much work on its main thread.
01-10 17:00:59.163: I/Choreographer(1975): Skipped 32 frames!  The application may be doing too much work on its main thread.
01-10 17:01:11.253: D/dalvikvm(1975): GC_FOR_ALLOC freed 74K, 5% free 5533K/5820K, paused 2ms, total 3ms
01-10 17:01:11.253: I/dalvikvm-heap(1975): Grow heap (frag case) to 7.992MB for 2500620-byte allocation
01-10 17:01:11.263: D/dalvikvm(1975): GC_FOR_ALLOC freed 2K, 4% free 7972K/8264K, paused 2ms, total 3ms
01-10 17:01:11.273: D/dalvikvm(1975): GC_FOR_ALLOC freed <1K, 4% free 7972K/8264K, paused 3ms, total 4ms
01-10 17:01:11.273: I/dalvikvm-heap(1975): Grow heap (frag case) to 10.696MB for 2838540-byte allocation
01-10 17:01:11.283: D/dalvikvm(1975): GC_FOR_ALLOC freed 0K, 3% free 10744K/11040K, paused 4ms, total 4ms
01-10 17:01:15.953: D/dalvikvm(1975): GC_FOR_ALLOC freed 5268K, 45% free 6880K/12360K, paused 0ms, total 3ms
01-10 17:01:15.953: I/dalvikvm-heap(1975): Grow heap (frag case) to 8.489MB for 1642512-byte allocation
01-10 17:01:15.973: D/dalvikvm(1975): GC_FOR_ALLOC freed <1K, 32% free 8483K/12360K, paused 13ms, total 13ms
01-10 17:01:16.053: I/Choreographer(1975): Skipped 42 frames!  The application may be doing too much work on its main thread.
01-10 17:01:17.473: I/Choreographer(1975): Skipped 58 frames!  The application may be doing too much work on its main thread.
01-10 17:01:18.043: I/Choreographer(1975): Skipped 57 frames!  The application may be doing too much work on its main thread.
01-10 17:01:23.363: D/AndroidRuntime(1975): Shutting down VM
01-10 17:01:23.363: W/dalvikvm(1975): threadid=1: thread exiting with uncaught exception (group=0xb0f2e648)
01-10 17:01:23.363: E/AndroidRuntime(1975): FATAL EXCEPTION: main
01-10 17:01:23.363: E/AndroidRuntime(1975): java.lang.NullPointerException
01-10 17:01:23.363: E/AndroidRuntime(1975):     at com.keyconsultant.parse.logintutorial.LoginFragment.onSaveInstanceState(LoginFragment.java:119)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.support.v4.app.Fragment.performSaveInstanceState(Fragment.java:1607)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1587)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1655)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:527)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.app.Activity.performSaveInstanceState(Activity.java:1147)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1223)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3714)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.app.ActivityThread.access$700(ActivityThread.java:141)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.os.Looper.loop(Looper.java:137)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at android.app.ActivityThread.main(ActivityThread.java:5103)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at java.lang.reflect.Method.invokeNative(Native Method)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at java.lang.reflect.Method.invoke(Method.java:525)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-10 17:01:23.363: E/AndroidRuntime(1975):     at dalvik.system.NativeStart.main(Native Method)

1 个答案:

答案 0 :(得分:0)

您的logcat显示您在LoginFragment.onSaveInstanceState()

中遇到问题

首先,使super.onSaveInstanceState()成为最后一行,而不是现在的第一行。

然后确保您没有mUserName和mPassword及其文本nulls

在某处将mUserName和密码文本初始化为“”,错误应该消失了。我想。