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

如何用ViewModel传递AlertDialog Fragment的结果?

问题:替代废弃API的简易DialogFragment结果回调方式

我有一个自定义DialogFragment,原本通过Intent和父组件通信,但用到的onActivityResult、getTargetFragment等方法已经废弃。我知道有新方法可以替代,但只是要获取Yes/No的结果,犯不上大费周章!有没有更简单的实现方式?我尝试用ViewModel但没成功!

我尝试的ViewModel代码

AlertDialogViewModel.java

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class AlertDialogViewModel extends ViewModel {
    private final MutableLiveData<Boolean> mAlertDialogResult = new MutableLiveData();
    
    public LiveData<Boolean> getAlertDialogResult() {
        return mAlertDialogResult;
    }
    
    public void setAlertDialogResult(boolean mResult) {
        mAlertDialogResult.setValue(mResult);
    }
}

MyAlertDialog.java

public class MyAlertDialog extends DialogFragment {
    AlertDialogViewModel mViewModel;

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        return new MaterialAlertDialogBuilder(requireContext())
                .setTitle(Title)
                .setMessage(MESSAGE)
                .setPositiveButton("YES", (d, b) -> onResult(true))
                .setNegativeButton("NO", (d, b) -> onResult(false))
                .create();
    }

    private void onResult(boolean result) {
       mViewModel.setAlertDialogResult(result);
    }
    
    public static void showResult(Fragment fragment) {
       MyAlertDialog dialog = new MyAlertDialog();
       dialog.show(fragment.getParentFragmentManager(), null);
    }
}

调用代码

MyAlertDialog.showResult(this);
AlertDialogViewModel model = new ViewModelProvider(this).get(AlertDialogViewModel.class);
model.getAlertDialogResult().observe(this, result-> {
    Toast.makeText(this, ""+result, Toast.LENGTH_SHORT).show();
});

问题分析

你的ViewModel方案失效的原因有两个:

  • ViewModel未初始化:DialogFragment里的mViewModel没有赋值,调用setAlertDialogResult时会直接空指针。
  • ViewModel作用域不共享:如果在DialogFragment里单独初始化ViewModel,默认会创建属于自己的实例,和宿主Fragment/Activity的ViewModel不是同一个,导致宿主观察不到结果。

两种简易解决方案

方案一:修复ViewModel共享逻辑

修改MyAlertDialog,让它使用宿主的ViewModelStoreOwner:

public class MyAlertDialog extends DialogFragment {
    private AlertDialogViewModel mViewModel;

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        // 使用宿主的ViewModelStoreOwner,保证和宿主共享同一个ViewModel实例
        mViewModel = new ViewModelProvider(requireParentFragment()).get(AlertDialogViewModel.class);
        // 如果是和Activity共享,就用:
        // mViewModel = new ViewModelProvider(requireActivity()).get(AlertDialogViewModel.class);
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        return new MaterialAlertDialogBuilder(requireContext())
                .setTitle("标题")
                .setMessage("提示内容")
                .setPositiveButton("YES", (d, b) -> {
                    mViewModel.setAlertDialogResult(true);
                    dismiss();
                })
                .setNegativeButton("NO", (d, b) -> {
                    mViewModel.setAlertDialogResult(false);
                    dismiss();
                })
                .create();
    }

    public static void showResult(Fragment fragment) {
        MyAlertDialog dialog = new MyAlertDialog();
        dialog.show(fragment.getParentFragmentManager(), "MyAlertDialog");
    }
}

调用逻辑不变,现在宿主就能正确观察到结果了。

方案二:更轻量的接口回调

如果只是需要Yes/No的简单结果,接口回调比ViewModel更直接,完全不需要额外依赖:

  1. 定义回调接口:
public interface AlertDialogCallback {
    void onDialogResult(boolean isPositive);
}
  1. 修改MyAlertDialog:
public class MyAlertDialog extends DialogFragment {
    private AlertDialogCallback mCallback;

    // 绑定回调,确保宿主实现了接口
    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        try {
            mCallback = (AlertDialogCallback) requireParentFragment();
            // 如果是和Activity绑定,就用:
            // mCallback = (AlertDialogCallback) requireActivity();
        } catch (ClassCastException e) {
            throw new ClassCastException("宿主必须实现AlertDialogCallback接口");
        }
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        return new MaterialAlertDialogBuilder(requireContext())
                .setTitle("标题")
                .setMessage("提示内容")
                .setPositiveButton("YES", (d, b) -> {
                    mCallback.onDialogResult(true);
                    dismiss();
                })
                .setNegativeButton("NO", (d, b) -> {
                    mCallback.onDialogResult(false);
                    dismiss();
                })
                .create();
    }

    public static void showResult(Fragment fragment) {
        MyAlertDialog dialog = new MyAlertDialog();
        dialog.show(fragment.getParentFragmentManager(), "MyAlertDialog");
    }
}
  1. 宿主实现接口并调用:
public class HostFragment extends Fragment implements AlertDialogCallback {
    // ... 其他代码

    private void showDialog() {
        MyAlertDialog.showResult(this);
    }

    @Override
    public void onDialogResult(boolean isPositive) {
        Toast.makeText(getContext(), isPositive ? "YES" : "NO", Toast.LENGTH_SHORT).show();
    }
}

这个方案代码更少,逻辑更直观,完全满足你“简单获取Yes/No结果”的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 06:27:59