DialogFragment中使用RxJava Observable设置AlertDialog属性偶现不生效
问题根因
onCreateDialog 是同步执行的方法,系统拿到你返回的 Dialog 实例后会立即触发渲染逻辑。而 myVM.getAllItems() 是异步数据库查询操作,回调执行时机晚于 builder.create() 和 Dialog 渲染流程,绝大多数情况下回调执行时 Dialog 已经完成显示,此时修改 AlertDialog.Builder 的参数不会同步到已经创建好的 Dialog 实例上,因此标题不会显示,仅在查询速度极快、回调赶在渲染前完成的极端场景下能正常展示。
解决方案
有两种常用的修复方式:
方案1:提前加载数据再创建Dialog
在宿主页面先完成数据查询,再把数据作为参数传入DialogFragment,创建Dialog时直接同步用数据配置Builder,从根源避免异步时序问题:
// 宿主页面创建DialogFragment的示例逻辑 myVM.getAllItems().observe(this, items -> { MyDialogFragment dialog = MyDialogFragment.newInstance(items); dialog.show(getSupportFragmentManager(), "dialog_tag"); }); // DialogFragment内部接收参数同步配置 public class MyDialogFragment extends DialogFragment { private static final String ARG_ITEMS = "arg_items"; public static MyDialogFragment newInstance(List<Item> items) { MyDialogFragment fragment = new MyDialogFragment(); Bundle args = new Bundle(); args.putParcelableArrayList(ARG_ITEMS, new ArrayList<>(items)); fragment.setArguments(args); return fragment; } public Dialog onCreateDialog(Bundle savedInstanceState){ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); List<Item> items = getArguments().getParcelableArrayList(ARG_ITEMS); builder.setTitle("Title"); // 直接同步设置多选列表 // builder.setMultiChoiceItems(...) return builder.create(); } }
方案2:异步回调后直接更新已创建的Dialog
如果必须在DialogFragment内部发起查询,可以在回调中直接操作已创建的Dialog实例更新UI,不要修改已执行过create的Builder参数:
public class MyDialogFragment extends DialogFragment { private AlertDialog mDialog; public Dialog onCreateDialog(Bundle savedInstanceState){ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); // 可先设置加载占位 builder.setTitle("加载中..."); MyViewModel myVM = new ViewModelProvider(this).get(MyViewModel.class); myVM.getAllItems().subscribe(items -> { if (mDialog != null && mDialog.isShowing()) { // 直接修改Dialog属性 mDialog.setTitle("Title"); // 设置多选列表可调用mDialog.getListView()相关方法配置 } }); mDialog = builder.create(); return mDialog; } }
内容的提问来源于stack exchange,提问作者Dingqing He
相关产品推荐
相关产品推荐

