【问题标题】:Activity crashes when dialogFragment is opened and onPause() is called打开 dialogFragment 并调用 onPause() 时 Activity 崩溃
【发布时间】:2018-03-06 16:42:05
【问题描述】:

我制作了一个自定义对话框(扩展了 DialogFragment),它出现在多个活动中。

如果在打开对话框时活动进入前台,我会收到以下错误:

 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

取决于活动或片段,“引起”的变化,因为问题不存在,是DialogFragment (不显示对话框片段一切正常)

有一个解决方案:在活动进入前台之前调用dismiss()。但是我必须写很多代码,因为我必须再次显示它,以防在活动进入前台之前打开对话框,而且由于活动的复杂性处理它并不简单。

我需要什么:在不关闭对话框的情况下解决问题。我认为我的 DialogFragment 类有错误。所以...这是我班级的代码:

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

如您所见,我必须在活动中处理两个回调。

那么...你有什么好办法解决这个问题吗?

谢谢!

编辑:

在任何活动中,我都必须像这样实现对话框:

MyActivity implements RequestDialog.MyDialogInterface

然后覆盖回调:

@Override
public void onClickContinuarEvent(int request) {
}

@Override
public void onClickCancelarEvent(int permisoRequerido) {}

【问题讨论】:

  • 您是否在onPause() 中保存任何数据?
  • 你最初是如何实例化callbackListener的?顺便说一句,序列化监听器似乎有点奇怪。
  • @ADM 不,我没有在 onPause() 中保存任何数据
  • 序列化奇怪的监听器。为什么不在已经拥有 object 的情况下为 listener 创建一个 setter。不要序列化接口为侦听器和检查创建一个设置器。
  • @DoronYakovlev-Golani 请看我刚刚编辑的帖子。这就是你的意思?

标签: android android-dialogfragment dialogfragment


【解决方案1】:

当片段/活动的生命周期终止时,您真的不应该制作任何应该终止的可序列化。对于此解决方案,请删除 getInstance() 上的接口。您不应该通过片段创建来传递接口。您应该为接口创建一个设置器。我没有足够的信息来解决这个问题,但我相信这可能是解决方案。让我知道它是否有效,因此如果无效,我可以删除。

对话框

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-05
    • 2016-08-27
    • 1970-01-01
    相关资源
    最近更新 更多