DialogFragment生命周期在旋转时的奇怪行为

时间:2018-04-05 11:25:17

标签: java android

我是Android开发中的新手,因此我坚持使用DialogFragment生命周期行为。我希望我的DialogFragment能够代表身份验证对话框,其中包含登录名和密码TextViews以及两个按钮。它似乎创造了两次。我试图记录生命周期,所以它的工作方式如下:

onAttach 
onCreate 
onCreateDialog 
onCreateView
onActivityCreated 
onViewStateRestored
onStart 
onResume 
onSaveInstanceState
onDetach 
onAttach 
onCreateDialog 
onCreateView
onActivityCreated 
onViewStateRestored
onAttach 
onCreate 
onCreateDialog 
onCreateView
onActivityCreated 
onViewStateRestored
onStart 
onStart 
onResume 
onResume 
onDetach 
onSaveInstanceState
onDetach 
onAttach 
onCreateDialog 
onCreateView
onActivityCreated 
onViewStateRestored
onAttach 1
onCreate 
onCreateDialog 
onCreateView
onActivityCreated 
onViewStateRestored
onStart 
onStart 
onResume 
onResume 
onDetach 

问题是,当我尝试旋转设备时,savedInstanceState设置为null,因为当它不是onAttach并且其他方法被调用时。这是我的DialogFragment代码:

public class SignInDialog extends DialogFragment implements View.OnClickListener{

private SignInDialogListener mSignInDialogListener;


private EditText mUsername;
private EditText mPassword;
private Button mReset;
private Button mLogin;
private Integer count=0;

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


    Log.v("test","onCreateView");


    this.getDialog().setTitle(R.string.login);

    mUsername = (EditText) view.findViewById(R.id.username);
    mPassword = (EditText) view.findViewById(R.id.password);
    mReset = (Button) view.findViewById(R.id.reset_button);
    mLogin = (Button) view.findViewById(R.id.login_button);
    setRetainInstance(true);//helps to avoid Dialog creates many times on rotation

    mReset.setOnClickListener(this);
    mLogin.setOnClickListener(this);

    return view;
}

public void onAttach(Activity context) {
    super.onAttach(context);
    count++;
    Log.v("test","onAttach "+count);
    // Verify that the host activity implements the callback interface
    try {
        // Instantiate the NoticeDialogListener so we can send events to the host
        mSignInDialogListener = (SignInDialogListener) context;
    } catch (ClassCastException e) {
        // The activity doesn't implement the interface, throw exception
        throw new ClassCastException(context.toString()
                + " must implement AuthenticationDialogListener");
    }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("login",mUsername.getText().toString());
    outState.putString("password",mPassword.getText().toString());
    Log.v("test","onSaveInstanceState");

}


@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
    super.onViewStateRestored(savedInstanceState);
    Log.v("test","onViewStateRestored");



}



@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Log.v("test","onCreateDialog ");
    return super.onCreateDialog(savedInstanceState);
}

public static SignInDialog newInstance() {
    return new SignInDialog();
}

public void onClick(View v) {
    if (v.equals(mLogin)) {
        if (mPassword.getText().toString().length() < 1) {
            Toast.makeText(getActivity(), R.string.invalid_password, Toast.LENGTH_SHORT).show();
            return;
        } else {
            mSignInDialogListener.onSignInDialogLoginClicked(mUsername.getText().toString(),
                    mPassword.getText().toString());
            this.dismiss();
        }
    } else if (v.equals(mReset)) {
        mSignInDialogListener.onSignInDialogResetClicked(mUsername.getText().toString());
    }
}


@Override
public void onActivityCreated(Bundle savedInstanceState) {
    Log.v("test","onActivityCreated ");
    super.onActivityCreated(savedInstanceState);
}

@Override
public void onStart() {
    Log.v("test","onStart ");
    super.onStart();
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    Log.v("test","onCreate ");
    super.onResume();
    super.onCreate(savedInstanceState);
}

@Override
public void onResume() {
    Log.v("test","onResume ");
    super.onResume();
}

@Override
public void onDetach() {
    Log.v("test","onDetach ");
    super.onDetach();
}

来自我创建DialogFragment

的活动的代码
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initializeActivity(savedInstanceState);
    }


    private void initializeActivity(Bundle savedInstanceState) {

        mSignInDialog = new SignInDialog();
        mSignInDialog.setCancelable(false);//to avoid back button pressed
        mSignInDialog.show(getSupportFragmentManager(), "Login");



        mToolbar = (Toolbar) findViewById(R.id.main_toolbar);
        mSearchRecyclerView = (RecyclerView) findViewById(R.id.search_recycler_view);
        mProgressBar = (ProgressBar) findViewById(R.id.search_progress_bar);
        setSupportActionBar(mToolbar);
        mSearchViewPresenter = new SearchViewPresenter(MainActivity.this);

    }

2 个答案:

答案 0 :(得分:0)

this link中解释:

  

某些设备配置可能会在运行时更改(例如屏幕方向,键盘可用性和语言)。发生此类更改时, Android会重新启动正在运行的活动(调用onDestroy(),然后调用onCreate())。

因此,当您旋转屏幕时,将处理销毁活动的整个过程,然后重新创建。附加到激活的片段遵循相同的过程。

对于已保存的实例问题,您可以关注documentation

答案 1 :(得分:0)

您可以检查您的片段是否已附加到当前片段管理器。如果已经添加,则可以关闭当前片段。

        @Override
        public void onAttach(Context context) {
            super.onAttach(context);

            Fragment loginFragment = getActivity().getFragmentManager().findFragmentByTag("Login");
            if(loginFragment != null){
                dismiss();
            }
        }

我假设你在活动

开始对话