Activity 在打开 dialogFragment 并调用 onPause() 时崩溃
Activity crashes when dialogFragment is opened and onPause() is called
我制作了一个出现在多个活动中的自定义对话框(扩展 DialogFragment)。
如果在打开对话框时 activity 出现在前台,我会收到以下错误:
FATAL EXCEPTION: main
Process: package.name, PID: 11137
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = myFragmentOrActivityWhereOccuredTheError)
...
Caused by: java.io.NotSerializableException: android.support.v7.widget.AppCompatButton
取决于activity或片段,"Caused by"变化,因为问题不在那里,是DialogFragment (不显示对话框片段一切正常)
有一个解决方案: 在 activity 进入前台之前调用 dismiss() 。但是我必须写很多代码,因为我必须再次显示它,以防在 activity 出现在前台之前打开对话框,而且由于活动的复杂性,处理起来并不简单。
我需要什么: 在不关闭对话框的情况下解决问题。我想我的 DialogFragment Class 有错误。所以...这是我的 class:
的代码
public class RequestDialog extends DialogFragment {
public static String DIALOG_INTERFACE = "dialogInterface";
public static String REQUIERE_ACTIVACION_MANUAL = "activationMode";
public static String SCHEME = "package";
public interface MyDialogInterface extends Serializable {
void onClickContinuarEvent(int permisoRequerido);
void onClickCancelarEvent(int permisoRequerido);
}
private MyDialogInterface callbackListener;
/**
* dialogInterface - instance of MyDialogInterface which will handle
* callback events
*/
public static RequestDialog getInstance(MyDialogInterface dialogInterface, boolean activationMode) {
RequestDialog fragmentDialog = new RequestDialog();
// set fragment arguments
Bundle args = new Bundle();
args.putSerializable(DIALOG_INTERFACE, dialogInterface);
args.putBoolean(REQUIERE_ACTIVACION_MANUAL, activationMode);
fragmentDialog.setArguments(args);
return fragmentDialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle extras = getArguments();
callbackListener = (MyDialogInterface) extras.getSerializable(DIALOG_INTERFACE);
final boolean activationMode = extras.getBoolean(REQUIERE_ACTIVACION_MANUAL);
View view = View.inflate(getActivity(), R.layout.rationale_dialog, null);
TextView texDetalle = view.findViewById(R.id.texDetalle);
TextView texContinuar = view.findViewById(R.id.texContinuar);
TextView texCancelar = view.findViewById(R.id.texCancelar);
ImageView imgCabecera = view.findViewById(R.id.imgCabecera);
imgCabecera.setBackground(ContextCompat.getDrawable(getActivity(), R.drawable.ic_folder));
Typeface typeFace = Typeface.createFromAsset(getActivity().getAssets(), "fonts/MyFont.ttf");
texDetalle.setTypeface(typeFace);
final AlertDialog.Builder requestDialogBuilder = new AlertDialog.Builder(getActivity(), R.style.NarrowDialog);
requestDialogBuilder.setView(view);
final AlertDialog dialog = requestDialogBuilder.create();
dialog.setContentView(view);
final Window window = dialog.getWindow();
if(window != null){
window.setLayout(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
window.setGravity(Gravity.CENTER);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
Display display = getActivity().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
dialog.getWindow().setLayout(size.x*70/100, WindowManager.LayoutParams.WRAP_CONTENT);
texContinuar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(activationMode){
goToPreferencesSystem();
callbackListener.onClickCancelarEvent(1);
}
else{
callbackListener.onClickContinuarEvent(0);
}
dialog.dismiss();
}
});
texCancelar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callbackListener.onClickCancelarEvent(2);
dialog.dismiss();
}
});
}
setCancelable(false);
return dialog;
}
}
如您所见,我必须在活动中处理两个回调。
所以...你有什么想法可以解决这个问题吗?
谢谢!
编辑:
在任何 activity 中,我都必须像这样实现对话框:
MyActivity implements RequestDialog.MyDialogInterface
然后覆盖回调:
@Override
public void onClickContinuarEvent(int request) {
}
@Override
public void onClickCancelarEvent(int permisoRequerido) {}
你真的不应该制作任何在 fragment/activity 的生命周期终止时应该终止的可序列化的东西。对于此解决方案,删除 getInstance() 上的接口。您不应该通过片段创建来传递接口。您应该为界面创建一个 setter。我几乎没有足够的信息来解决这个问题,但我相信这可能是解决方案。让我知道它是否有效,如果无效,我可以删除。
对话框
public class RequestDialog extends DialogFragment {
private MyDialogInterface callbackListener;
public interface MyDialogInterface {
void onClickContinuarEvent(int permisoRequerido);
void onClickCancelarEvent(int permisoRequerido);
}
public void setCallbackListener(MyDialogInterface callbackListener) {
this.callbackListener = callbackListener;
}
public static RequestDialog getInstance( boolean activationMode) {
RequestDialog fragmentDialog = new RequestDialog();
Bundle args = new Bundle();
args.putBoolean(REQUIERE_ACTIVACION_MANUAL, activationMode);
fragmentDialog.setArguments(args);
return fragmentDialog;
}
}
创建对话框
RequestDialog requestDialog = RequestDialog.getInstance(true);
requestDialog.setCallbackListener(new RequestDialog.MyDialogInterface() {
@Override
public void onClickContinuarEvent(int permisoRequerido) {
}
@Override
public void onClickCancelarEvent(int permisoRequerido) {
}
});
requestDialog.show(getSupportFragmentManager(), "REQUEST_DIALOG");
我制作了一个出现在多个活动中的自定义对话框(扩展 DialogFragment)。
如果在打开对话框时 activity 出现在前台,我会收到以下错误:
FATAL EXCEPTION: main
Process: package.name, PID: 11137
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = myFragmentOrActivityWhereOccuredTheError)
...
Caused by: java.io.NotSerializableException: android.support.v7.widget.AppCompatButton
取决于activity或片段,"Caused by"变化,因为问题不在那里,是DialogFragment (不显示对话框片段一切正常)
有一个解决方案: 在 activity 进入前台之前调用 dismiss() 。但是我必须写很多代码,因为我必须再次显示它,以防在 activity 出现在前台之前打开对话框,而且由于活动的复杂性,处理起来并不简单。
我需要什么: 在不关闭对话框的情况下解决问题。我想我的 DialogFragment Class 有错误。所以...这是我的 class:
的代码public class RequestDialog extends DialogFragment {
public static String DIALOG_INTERFACE = "dialogInterface";
public static String REQUIERE_ACTIVACION_MANUAL = "activationMode";
public static String SCHEME = "package";
public interface MyDialogInterface extends Serializable {
void onClickContinuarEvent(int permisoRequerido);
void onClickCancelarEvent(int permisoRequerido);
}
private MyDialogInterface callbackListener;
/**
* dialogInterface - instance of MyDialogInterface which will handle
* callback events
*/
public static RequestDialog getInstance(MyDialogInterface dialogInterface, boolean activationMode) {
RequestDialog fragmentDialog = new RequestDialog();
// set fragment arguments
Bundle args = new Bundle();
args.putSerializable(DIALOG_INTERFACE, dialogInterface);
args.putBoolean(REQUIERE_ACTIVACION_MANUAL, activationMode);
fragmentDialog.setArguments(args);
return fragmentDialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle extras = getArguments();
callbackListener = (MyDialogInterface) extras.getSerializable(DIALOG_INTERFACE);
final boolean activationMode = extras.getBoolean(REQUIERE_ACTIVACION_MANUAL);
View view = View.inflate(getActivity(), R.layout.rationale_dialog, null);
TextView texDetalle = view.findViewById(R.id.texDetalle);
TextView texContinuar = view.findViewById(R.id.texContinuar);
TextView texCancelar = view.findViewById(R.id.texCancelar);
ImageView imgCabecera = view.findViewById(R.id.imgCabecera);
imgCabecera.setBackground(ContextCompat.getDrawable(getActivity(), R.drawable.ic_folder));
Typeface typeFace = Typeface.createFromAsset(getActivity().getAssets(), "fonts/MyFont.ttf");
texDetalle.setTypeface(typeFace);
final AlertDialog.Builder requestDialogBuilder = new AlertDialog.Builder(getActivity(), R.style.NarrowDialog);
requestDialogBuilder.setView(view);
final AlertDialog dialog = requestDialogBuilder.create();
dialog.setContentView(view);
final Window window = dialog.getWindow();
if(window != null){
window.setLayout(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
window.setGravity(Gravity.CENTER);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
Display display = getActivity().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
dialog.getWindow().setLayout(size.x*70/100, WindowManager.LayoutParams.WRAP_CONTENT);
texContinuar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(activationMode){
goToPreferencesSystem();
callbackListener.onClickCancelarEvent(1);
}
else{
callbackListener.onClickContinuarEvent(0);
}
dialog.dismiss();
}
});
texCancelar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callbackListener.onClickCancelarEvent(2);
dialog.dismiss();
}
});
}
setCancelable(false);
return dialog;
}
}
如您所见,我必须在活动中处理两个回调。
所以...你有什么想法可以解决这个问题吗?
谢谢!
编辑:
在任何 activity 中,我都必须像这样实现对话框:
MyActivity implements RequestDialog.MyDialogInterface
然后覆盖回调:
@Override
public void onClickContinuarEvent(int request) {
}
@Override
public void onClickCancelarEvent(int permisoRequerido) {}
你真的不应该制作任何在 fragment/activity 的生命周期终止时应该终止的可序列化的东西。对于此解决方案,删除 getInstance() 上的接口。您不应该通过片段创建来传递接口。您应该为界面创建一个 setter。我几乎没有足够的信息来解决这个问题,但我相信这可能是解决方案。让我知道它是否有效,如果无效,我可以删除。
对话框
public class RequestDialog extends DialogFragment {
private MyDialogInterface callbackListener;
public interface MyDialogInterface {
void onClickContinuarEvent(int permisoRequerido);
void onClickCancelarEvent(int permisoRequerido);
}
public void setCallbackListener(MyDialogInterface callbackListener) {
this.callbackListener = callbackListener;
}
public static RequestDialog getInstance( boolean activationMode) {
RequestDialog fragmentDialog = new RequestDialog();
Bundle args = new Bundle();
args.putBoolean(REQUIERE_ACTIVACION_MANUAL, activationMode);
fragmentDialog.setArguments(args);
return fragmentDialog;
}
}
创建对话框
RequestDialog requestDialog = RequestDialog.getInstance(true);
requestDialog.setCallbackListener(new RequestDialog.MyDialogInterface() {
@Override
public void onClickContinuarEvent(int permisoRequerido) {
}
@Override
public void onClickCancelarEvent(int permisoRequerido) {
}
});
requestDialog.show(getSupportFragmentManager(), "REQUEST_DIALOG");