You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fragment中调用getSupportFragmentManager()显示Dialog失败问题

Android Fragment内DialogFragment显示异常修复方案

问题描述

主Activity为带TabLayout和ViewPager的仪表盘,菜单点击功能正常,但Fragment内调用DialogFragment时出现异常,相同代码在普通Activity中可正常运行,尝试多种论坛方案未解决。

相关代码

ScanTabFragment代码

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

public class ScanTabFragment extends Fragment implements View.OnClickListener, ProjectDialogActivity.DialogListener{

private CardView cardViewCreateProjectBatch;
private View view;
private DatabaseHelperBatch mySQLiteAdapterBatch; // 补充声明变量

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_scan_tab, container, false);
        cardViewCreateProjectBatch = view.findViewById(R.id.cardViewCreateProjectBatch);
        cardViewCreateProjectBatch.setOnClickListener(this);

        return view;
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
                case R.id.cardViewCreateProjectBatch:
                newProjectDialog();
                break;
        }
    }

 private void newProjectDialog() {
        String projectNameAuto = "PJ-Batch-" + android.text.format.DateFormat.format("yyyy.MM.dd.kk.mm.ss", new java.util.Date());
        FragmentManager fm = getSupportFragmentManager(); // 此处获取方式错误
        
        // 尝试过的错误写法
        //FragmentManager fm = getActivity().getSupportFragmentManager();
        //FragmentManager fm = this.getParentFragment().getChildFragmentManager();
        //FragmentManager fm = this.getParentFragment().getFragmentManager();
        //FragmentManager fm = this.getParentFragment().getFragmentManager().beginTransaction();
        //FragmentManager fm = this.getChildFragmentManager();
        //FragmentManager fm = getFragmentManager();
        //FragmentManager fm = getParentFragment();

        ProjectDialogActivity alertDialog = ProjectDialogActivity.newInstance("Create New Batch Project", projectNameAuto, "");
        alertDialog.setCancelable(false);
        alertDialog.show(fm, "fragment_alert");

        // 重复创建Dialog实例
        ProjectDialogActivity alertDialog = ProjectDialogActivity.newInstance("Create New Batch Project", projectNameAuto, "");
        alertDialog.setCancelable(false);
        alertDialog.show(fm, "fragment_alert");
        }

public long insertProject1(String project_name, String created_date, Integer status, String notes) {
        mySQLiteAdapterBatch = new DatabaseHelperBatch(view.getContext());
        SQLiteDatabase db = mySQLiteAdapterBatch.getWritableDatabase();

        ContentValues contentValues = new ContentValues();
        contentValues.put("project_name", project_name);
        contentValues.put("created_date", created_date);
        contentValues.put("status", status);
        contentValues.put("notes", notes);

        return db.insert("project1", null, contentValues);
    }

public long insertProject2(String project_name, String created_date, Integer status, String notes) {
        mySQLiteAdapterBatch = new DatabaseHelperBatch(view.getContext());
        SQLiteDatabase db = mySQLiteAdapterBatch.getWritableDatabase();

        ContentValues contentValues = new ContentValues();
        contentValues.put("project_name", project_name);
        contentValues.put("created_date", created_date);
        contentValues.put("status", status);
        contentValues.put("notes", notes);

        return db.insert("project2", null, contentValues);
    }

 @Override
    public void applyTexts(String project_name, String created_date, Integer status, String notes) {
        if (ProjectDialogActivity.radioButtonProject1.isChecked() == true) {
            insertProject1(project_name, created_date, status, notes);
            Toast.makeText(view.getContext(), "New Batch project1 has been created", Toast.LENGTH_LONG).show();
        }

        if (ProjectDialogActivity.radioButtonProject2.isChecked() == true) {
            insertProject2(project_name, created_date, status, notes);
            Toast.makeText(view.getContext(), "New Batch project2 has been created", Toast.LENGTH_LONG).show();
        }
    }
}

ProjectDialogActivity(DialogFragment)代码

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatDialogFragment;
import java.util.Calendar;

public class ProjectDialogActivity extends AppCompatDialogFragment {
    private String projectName;
    private String projectCreated;
    private String projectNotes;
    private Integer projectStatus;

    private TextView textViewProjectName;
    private TextView textViewNotes;

    public static RadioButton radioButtonProject1; // 静态变量存在风险
    public static RadioButton radioButtonProject2;

    public static ProjectDialogActivity newInstance(String title, String getProjectName, String getNotes) {
        ProjectDialogActivity frag = new ProjectDialogActivity();
        Bundle args = new Bundle();
        args.putString("title", title);
        args.putString("inputProjectName", getProjectName);
        args.putString("inputNotes", getNotes);
        frag.setArguments(args);
        return frag;
    }

    private DialogListener listener;

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        String title = getArguments().getString("title");
        String inputProjectName = getArguments().getString("inputProjectName");
        String inputNotes = getArguments().getString("inputNotes");

        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        LayoutInflater inflater = getActivity().getLayoutInflater();
        final View view = inflater.inflate(R.layout.activity_projectdialog, null);

        radioButtonProject1 = view.findViewById(R.id.radioButtonScan1);
        radioButtonProject2 = view.findViewById(R.id.radioButtonScan2);

        textViewProjectName = view.findViewById(R.id.editTextProjectName);
        textViewNotes = view.findViewById(R.id.editTextNotes);

        textViewProjectName.setSingleLine(true);
        textViewNotes.setSingleLine(true);

        textViewProjectName.setText(inputProjectName);
        textViewNotes.setText(inputNotes);

        projectName = textViewProjectName.getText().toString();

        builder.setView(view)
                .setTitle(title)
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialoginterface, int i) {
                        dialoginterface.cancel();
                    }
                })
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });
        return builder.create();
    }

    @Override
    public void onResume() {
        super.onResume();
        final AlertDialog d = (AlertDialog) getDialog();
        if (d != null) {
            Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE);
            positiveButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    projectName = textViewProjectName.getText().toString();
                    projectCreated = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
                    projectStatus = 0;
                    projectNotes = textViewNotes.getText().toString();
                    Boolean wantToCloseDialog;
                    
                    if (projectName.isEmpty()) {
                        Toast.makeText(getContext(), "Cannot left blank, Please input your project name", Toast.LENGTH_LONG).show();
                        textViewProjectName.requestFocus();
                        wantToCloseDialog = false;
                    } else {
                        wantToCloseDialog = true;
                    }

                    if (wantToCloseDialog == true) {
                        listener.applyTexts(projectName, projectCreated, projectStatus, projectNotes);
                        d.dismiss();
                    }
                }
            });
        }
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        try {
            listener = (DialogListener) context; // 绑定到Activity,而非Fragment
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString() + " must implement DialogListener");
        }
    }

    public interface DialogListener {
        void applyTexts(String project_name, String created_date, Integer status, String Notes);
    }
}

修复步骤

1. 修正FragmentManager获取方式

在ScanTabFragment的newProjectDialog()方法中,使用getChildFragmentManager()获取FragmentManager,用于管理当前Fragment的子DialogFragment:

private void newProjectDialog() {
    String projectNameAuto = "PJ-Batch-" + android.text.format.DateFormat.format("yyyy.MM.dd.kk.mm.ss", new java.util.Date());
    FragmentManager fm = getChildFragmentManager(); // 正确获取方式

    ProjectDialogActivity alertDialog = ProjectDialogActivity.newInstance("Create New Batch Project", projectNameAuto, "");
    alertDialog.setCancelable(false);
    alertDialog.show(fm, "fragment_alert");
}

同时删除重复创建Dialog的代码段。

2. 修复DialogListener绑定逻辑

修改ProjectDialogActivity的onAttach方法,优先从父Fragment获取Listener,确保实现了接口的Fragment能接收回调:

@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    if (getParentFragment() instanceof DialogListener) {
        listener = (DialogListener) getParentFragment();
    } else if (context instanceof DialogListener) {
        listener = (DialogListener) context;
    } else {
        throw new ClassCastException(context.toString() + " 必须实现DialogListener");
    }
}

3. 移除静态RadioButton,传递选中状态

  • 去掉radioButtonProject1和radioButtonProject2的static修饰符
  • 更新DialogListener接口,添加选中状态参数:
public interface DialogListener {
    void applyTexts(String project_name, String created_date, Integer status, String Notes, boolean isProject1Checked);
}
  • 修改ProjectDialogActivity的onResume方法,传递选中状态:
if (wantToCloseDialog == true) {
    boolean isProject1Checked = radioButtonProject1.isChecked();
    listener.applyTexts(projectName, projectCreated, projectStatus, projectNotes, isProject1Checked);
    d.dismiss();
}
  • 在ScanTabFragment中更新applyTexts实现:
@Override
public void applyTexts(String project_name, String created_date, Integer status, String notes, boolean isProject1Checked) {
    if (isProject1Checked) {
        insertProject1(project_name, created_date, status, notes);
        Toast.makeText(view.getContext(), "New Batch project1 has been created", Toast.LENGTH_LONG).show();
    } else {
        insertProject2(project_name, created_date, status, notes);
        Toast.makeText(view.getContext(), "New Batch project2 has been created", Toast.LENGTH_LONG).show();
    }
}

4. 优化数据库重复代码

合并insertProject1和insertProject2为一个通用方法:

public long insertProject(String tableName, String project_name, String created_date, Integer status, String notes) {
    mySQLiteAdapterBatch = new DatabaseHelperBatch(view.getContext());
    SQLiteDatabase db = mySQLiteAdapterBatch.getWritableDatabase();

    ContentValues contentValues = new ContentValues();
    contentValues.put("project_name", project_name);
    contentValues.put("created_date", created_date);
    contentValues.put("status", status);
    contentValues.put("notes", notes);

    return db.insert(tableName, null, contentValues);
}

然后在applyTexts中调用:

if (isProject1Checked) {
    insertProject("project1", project_name, created_date, status, notes);
    Toast.makeText(view.getContext(), "New Batch project1 has been created", Toast.LENGTH_LONG).show();
} else {
    insertProject("project2", project_name, created_date, status, notes);
    Toast.makeText(view.getContext(), "New Batch project2 has been created", Toast.LENGTH_LONG).show();
}

内容的提问来源于stack exchange,提问作者ed ed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 08:25:42