如何避免Android应用程序崩溃,当自定义对话片段中的setOwnerActivity(Activity activi



我在使用 Sharedpreferences 和 DialogFragment 时遇到了一个非常奇怪的异常:

Unable to start activity ComponentInfo{com.example.barta1.site_patrol/com.example.barta1.site_patrol.MainActivity}: 
java.lang.NullPointerException: Attempt to invoke virtual method
'void android.app.Dialog.setOwnerActivity(android.app.Activity)'
on a null object reference  -  
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2679)

我真的不知道是什么导致了这个错误,但是发生这种情况后,我永远无法开始 我的应用程序再次出现,它不断崩溃,出现上述相同异常。MainActivity 是我在应用程序中的启动活动,附加了一个 DialogFragment,我用它来登录用户。如果用户未登录("已登录"状态保存在共享首选项对象中(,我会显示此对话框片段。

我的主要活动是这样的:

public class MainActivity extends AppCompatActivity implements LoginDialogFragment.NoticeDialogListener {
//...
private LoginDialogFragment dialogFragment;
SharedPreferences pref;
SharedPreferences.Editor edit;
//...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pref = getSharedPreferences("Globals", MODE_PRIVATE);
edit = pref.edit();
boolean isloggedin = pref.getBoolean("Loggedin", false);

if (!isloggedin) {
//if not logged in show the login dialog
showLoginDialog();
} 
else {
//... doing some network calls...
}
}
public void showLoginDialog() {
dialogFragment = new LoginDialogFragment();
dialogFragment.show(getFragmentManager(), "LoginDialogFragment");
}
/***
* Network calls if dialog dismissed
* Login dialog can only be closed if logging in is successful
* (if loginname and password matches). 
*/
@Override
public void onDismiss() {
//... some network related jobs
}
}

这是片段类:

public class LoginDialogFragment extends DialogFragment {
public interface NoticeDialogListener{
void onDismiss();
}
NoticeDialogListener mListener;
Activity activity;
AlertDialog dialog;
SharedPreferences pref;
SharedPreferences.Editor edit;

@Override
public void onAttach(Context context) {
super.onAttach(context);
try{
activity = (Activity) context;
mListener = (NoticeDialogListener) activity;
pref = activity.getSharedPreferences("Globals", MODE_PRIVATE);
edit = pref.edit();
} catch (ClassCastException e){
throw new ClassCastException(activity.toString() + "must implement NoticeDialogListener");
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String username = pref.getString("Username", null);
if(username==null) {
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.dialog_signin, null);
final AutoCompleteTextView actv_username =  view.findViewById(R.id.username);
final EditText password =  view.findViewById(R.id.password);
dialog = new AlertDialog.Builder(new ContextThemeWrapper(getContext(), R.style.AlertDialogCustom))
.setView(view)
.setTitle("Bejelentkezés")
.setPositiveButton("OK", null)
.create();

dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
final Button button = ( dialog).getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String passw = password.getText().toString();
String user = actv_username.getText().toString();
try {
if (user.length() < 4 || passw.length() < 4) {
Toast.makeText(getContext(), "Too short user/pass.", Toast.LENGTH_SHORT).show();
dialog.show();
} else {
//login to account, if success dismiss.
login(user, passw, dialog);
}

} catch (Exception e) {
e.printStackTrace();
}
//  dialog.dismiss();
}
});
}
});
dialog.setCanceledOnTouchOutside(false);
// set the DialogFragment to make the dialog unable to dismiss with back button
// (because not working if called on the dialog directly)
this.setCancelable(false);
return dialog;
} // end of - if username == null.
return null;
}
public void login(final String username, String password, final AlertDialog dialog){
//... some network call
//... if successful: 
//              edit.putString("Username", username);
//              edit.commit();
//              edit.putBoolean("Loggedin", true);
//              edit.commit();
//              dialog.dismiss();
//              dialog.setOnShowListener(null);
//     
//     else 
//              Toast.makeText(getContext(),"Wrong login credentials", 
//                   Toast.LENGTH_SHORT).show();
}

@Override
public void onDismiss(DialogInterface dialog) {
mListener.onDismiss();
dismissAllowingStateLoss();
}

重新安装软件包后,我无法重新创建此异常(即使我杀死了应用程序进程,并从最近的应用程序启动它(,最终用户以某种方式设法做到了这一点和那个时间,重新启动应用程序是即时崩溃(请参阅上面的异常。看起来父活动以某种方式变为空(在保存状态后可能,之后无法恢复(。

将来如何避免这种情况?有没有简单的方法可以处理这种情况?

如果有人可以向我解释何时调用android库中的"setOwnerActivity(Activity activity(",那也将是一个很大的帮助,这样我就可以确定出了什么问题。

感谢您的任何帮助。

正如Mike M.所说,

您不能从 onCreateDialog(( 返回 null。取消或中止对话框显示为时已晚。

创建片段之前的用户名检查显然可以解决问题。此外,"登录"字段现在看起来是多余的。

最新更新