【发布时间】:2019-12-07 10:58:36
【问题描述】:
我在使用 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,我用它来登录用户。如果用户未登录(“登录”状态保存在 sharedpreference 对象中),我会显示此对话框片段。
我的 MainActivity 是这样的:
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)”,那也将是一个很大的帮助,这样我就可以确定出了什么问题。
感谢您的帮助。
【问题讨论】:
-
您不能从
onCreateDialog()返回 null。取消或中止Dialog显示为时已晚。请改为使用username签入showLoginDialog()。 -
Awww 男人。这是有史以来最快的答案。你是对的,这导致了异常。非常感谢!
标签: java android nullpointerexception sharedpreferences dialogfragment