简体   繁体   中英

Activity crashes when dialogFragment is opened and onPause() is called

I made a custom dialog (extends DialogFragment) that appears in several activities.

If the activity comes to foreground while the dialog is opened, I get the following error:

 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

Depends on the activity or fragment, "Caused by" changes, because the problem is not there, is the DialogFragment (without showing the dialog fragments everything works)

There is a solution: calling dismiss() before the activity goes to foreground. But I have to write a lot of code because I have to show it again in case the dialog was opened before the activity came to foreground and also is not simple to handle that with the complexity of the activies.

What I need: Solve the problem without dismissing the dialog. I think I have an error on my DialogFragment Class. So... this is the code of my 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;
    }
}

As you can see, there is two callback that I have to handle in the activies.

So... Do you have any idea hoy to solve this problem?

Thanks!

EDIT:

In any activity I have to implement the dialog like this:

MyActivity implements RequestDialog.MyDialogInterface

And then override the callbacks:

@Override
public void onClickContinuarEvent(int request) {
}

@Override
public void onClickCancelarEvent(int permisoRequerido) {}

You really should not be making anything Serializable that should die when the lifecycle of a fragment/activity die. For this solution, remove the interface on the getInstance(). You should not pass interfaces via fragment creation. You should create a setter for the interface. I don't have nearly enough information to solve the issue but, I believe this may be the solution. Let me know if it works, so I can delete if it it doesn't.

Dialog

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;
    }
}

Create Dialog

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");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM