Android导航对话框片段回调

Android导航对话框片段回调,android,mvvm,android-dialogfragment,android-jetpack,Android,Mvvm,Android Dialogfragment,Android Jetpack,我的项目(MVVM,Jetpack navigation)中有DialogFragment,它从不同的地方调用并表示签名画布。导航相关部分: <dialog android:id="@+id/signPadDialogFragment" android:name="com.ui.signpad.SignPadDialogFragment" android:label="SignPadDialogFragment" /> <f

我的项目(MVVM,Jetpack navigation)中有DialogFragment,它从不同的地方调用并表示签名画布。导航相关部分:

 <dialog
        android:id="@+id/signPadDialogFragment"
        android:name="com.ui.signpad.SignPadDialogFragment"
        android:label="SignPadDialogFragment" />

 <fragment
        android:id="@+id/loginFragment"
        android:name="com.ui.login.LoginFragment"
        android:label="@string/login_label"
        tools:layout="@layout/login_fragment">

        <action
            android:id="@+id/action_loginFragment_to_currentJobsFragment"
            app:destination="@id/currentJobsFragment" />
        <action
            android:id="@+id/action_loginFragment_to_signPadDialogFragment"
            app:destination="@id/signPadDialogFragment" />

<fragment
        android:id="@+id/jobDetailFragment"
        android:name="com.ui.jobdetails.JobDetailFragment"
        android:label="job_detail_fragment"
        tools:layout="@layout/job_detail_fragment" >
        <action
            android:id="@+id/action_jobDetailFragment_to_signPadDialogFragment"
            app:destination="@id/signPadDialogFragment" />
    </fragment>
所以,我的问题是:使用Jetpack导航和MVVM处理回调的正确方法是什么? 我看到两个可能的解决方案和相关问题:

我可以将数据从对话框片段传递到ViewModel->Repository(在本例中:如何区分在对话框范围内启动对话框的操作?

或者在MainActivity中获得回调(如何?)


提前感谢

由于
导航控制器API的限制,只能从存在android
上下文的元素中发现它。这意味着您的主要选择是:

  • AndroidViewModel:我不推荐它,因为它很容易被这里的上下文冲昏头脑,如果您不知道自己在做什么,这将导致内存泄漏
  • 活动:处理活动中的导航。单活动体系结构将使问题复杂化,因为您必须限制这里的所有导航逻辑
  • 片段:处理其范围内每个片段的导航。这是更好的方法,但下面有一个更好的解决方案
  • ViewModel:在其作用域内的ViewModel中处理每个片段的导航。(个人偏好)
  • 在Jetpack导航组件中使用ViewModel 从技术上讲,导航登录仍将驻留在
    片段中
    ,除非
    导航API
    发生更改,否则无法避免,但是我们可以将主要部分委托给
    视图模型
    ,如下所示:

  • ViewModel将公开一个
    SingleLiveEvent
    并在其中封装一个
    NavDirection
    SingleLiveEvent
    是一种只触发一次的实时数据,这是我们在导航时需要的。Jose Alcérreca写了一篇很棒的博客:

  • Fragment
    将观察此
    SingleLiveEvent
    ,并将使用该
    导航方向执行导航事务

  • ViewModel公开SingleLiveEvent: 您可以使用
    BaseFragment
    BaseViewModels
    来遵循
    ,但请始终记住,任何以
    作为前缀的内容都会很快变成代码气味,因此请尽可能简洁

     mainActivityViewModel.repository.navigationCommands.observe(this, Observer { navEvent ->
                navEvent.getContentIfNotHandled()?.let {
                    navController.navigate(it as NavDirections)
                }
    
            })
    
    open class BaseViewModel : ViewModel() {
      /**
       * Navigation Component API allows working with NavController in the Following:
       * 1.) Fragment
       * 2.) Activity
       * 3.) View
       *
       * In order to delegate the navigation logic to a viewModel and allow fragment
       * or an activity to communicate with viewModel, we expose navigationCommands
       * as LiveData that contains Event<NavigationCommand> value.
       *
       * Event<T> is simply a wrapper class that will only expose T if it has not
       * already been accessed with the help of a Boolean flag.
       *
       * NavigationCommand is a Sealed class which creates a navigation hierarchy
       * where child classes can take NavDirections as properties. We will observe the
       * value of NavigationCommand in the fragment and pull the NavDirections there.
       */
      private val _navigationCommands = MutableLiveData<Event<NavigationCommand>>()
      val navigationCommands: LiveData<Event<NavigationCommand>>
        get() = _navigationCommands
    
      fun navigate(directions: NavDirections) {
        _navigationCommands.postValue(Event(NavigationCommand.To(directions)))
      }
    }
    
      private fun setupNavigation() {
        viewModel.navigationCommands.observe(viewLifecycleOwner, Observer {
          val navigationCommand = it.getContentIfNotHandled()
    
          when (navigationCommand) {
            is NavigationCommand.To -> { findNavController().navigate(navigationCommand.directions) }
          }
        })
      }