MVVM架构中从ViewModel启动Activity的最佳方法

8

我在应用中采用了MVVM架构,一切都很好,直到我使用以下代码从ViewModel启动Activity时发生崩溃。该方法是通过数据绑定从XML调用的,并传递view作为参数,getApplication()AndroidViewModel类的方法。

getApplication().startActivity(new Intent(view.getContext(), MyActivity.class));

我认为这是因为我在Activity类外启动活动时没有使用NEW_TASK标志。
现在有以下解决方案,但不确定哪个从架构角度来看最好。
1. ViewModel带有一个以Activity作为参数的方法,并从片段调用该方法。
public startMyActivity(Activity activity){
   activity.startActivity(new Intent(activity, MyActivity.class));
}

现在在fragment中添加一个类似以下的监听器:

mBinding.myButton.setOnClickListener(){
    viewModel.startMyActivity(getActivity());  
}

2. 向意图添加新的任务标志并将其保留在ViewModel中

Intent myIntent = new Intent(view.getContext(), MyActivity.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
getApplication().startActivity(myIntent);

3.从片段自身启动活动

mBinding.myButton.setOnClickListener(){
   activity.startActivity(new Intent(activity, MyActivity.class));
}

我相信所有这些方法都可以很好地工作,但脑海中有一个问题:在Fragment中单独使用侦听器而不是使用绑定的ViewModel从视图xml调用方法是否可以?从架构角度和单元测试的角度来看,哪种方法是最好的?我对第二种方法还不确定,在某些操作系统中是否仍会导致应用程序崩溃。

在ViewModel或AndroidViewModel中,必须避免使用任何Android视图。 - Chintan Soni
@ChintanSoni 我同意,它不是一个引用,它是从数据绑定传递给单击监听器方法的,我认为这应该没问题。 - Piyush Agarwal
@MuhammadBabar 谁应该启动活动,如何启动,因为理想情况下,所有视图交互都应在视图模型中处理。 - Piyush Agarwal
是的,你说得对。这要看情况而定。如果有活动上下文可用,那么最好使用NEW_TASK。例如,在广播接收器或服务中没有可用的活动上下文。 - Muhammad Babar
1个回答

8
我会选择在活动/片段内进行导航,但是大多数情况下,您需要从视图模型触发导航。 因此,您需要使用来自视图模型的命令通知视图(活动/片段)导航到其他地方。 您可以使用LiveData和更具体地说SingleLiveEvent来执行此类“命令”。
SingleLiveEvent就像任何LiveData一样,但只有在您明确为其设置值时才触发事件,例如,当您从视图(活动/片段)开始观察它时,您不会收到其值。

谢谢,我会尝试一下并看看是否适用于我。 - Piyush Agarwal
如果当前屏幕有多个可能的目标,我应该为每个可能的目标都有一个SingleLiveEvent吗?这方面有什么最佳实践吗? - Archie G. Quiñones
我将使用一个事件和目的地作为参数。 - Samuel Eminet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接