为什么从片段触发导航?

时间:2019-10-11 13:25:09

标签: android kotlin mvvm

我正在尝试根据MVVM模式设置项目,并且正在使用Jetpack的Android体系结构组件。

我有一个“ splash”片段,在该片段中发出HTTP请求,并且根据响应,用户将被导航到设置视图或主视图。

FragmentSplash:

class FragmentSplash : Fragment()
{
    private lateinit var viewModelSplash: ViewModelSplash

    override fun onCreateView( inflater: LayoutInflater,
                               container: ViewGroup?,
                               savedInstanceState: Bundle? ): View?
    {
        viewModelSplash = ViewModelProviders.of( this ).get( ViewModelSplash::class.java )
        return inflater.inflate(com.host.myproject.R.layout.fragment_splash, container, false )
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?)
    {
        viewModelSplash.command.observe(this, Observer {
            when( it ) // I know strings are bad :)
            {
                "NAVIGATE_TO_MAIN" -> Navigation.findNavController( view ).navigate( R.id.action_showConfirm )
                "NAVIGATE_TO_"     -> Navigation.findNavController( view ).navigate( R.id.action_showBase )
            }
        });

        super.onViewCreated(view, savedInstanceState)
    }
}

ViewModelSplash:

class ViewModelSplash : ViewModel()
{
    private val _command = MutableLiveData<String>()
    val command: LiveData<String>
        get() = _command

    init
    {
        Timer("fakeHTTPRequest", false).schedule(3500) {
            onInitializationFinished( response )
        }
    }

    private fun onInitializationFinished( response : Response )
    {
        if( response.ok )
            _command.postValue( "NAVIGATE_TO_MAIN" )
        else
            _command.postValue( "NAVIGATE_TO_CONFIRM" )
    }
}

我看到的问题是:

-The FragmentSplash contains logic pattern the "when" statement
-The FragmentSplash is aware of other fragments

我正在尝试了解实现此目标的正确方法是什么,因为到目前为止,我所看到的所有示例都在ViewModel更改了可观察对象内的数据之后在Fragment中调用了导航器:

viewModelSplash.command.observe(this, Observer {
...
    Navigation.findNavController( view ).navigate
...

我完全迷路了。.不是

  

与“观点/逻辑的独立性”矛盾吗?

我认为应该有某种Router类,该类从ViewModel获取通知,该类需要导航到其他地方,这样视图将完全干净。有什么建议可以从这里走吗?

1 个答案:

答案 0 :(得分:0)

您可以尝试使导航命令在视图模型中包含实时数据,并在BaseFragment中对其进行观察。假设您要从片段A导航到片段B,然后:

导航命令

sealed class NavigationCommand {
  data class navigateTo(val directions: NavDirections): NavigationCommand()
  object Back: NavigationCommand()
}

在BaseFragment中

viewModel.navigationCommands.observe { command ->
    when (command) {
      is NavigationCommand.navigateTo ->      
        findNavController().navigate(command.directions)
      NavigationCommand.Back ->      
        findNavController().popBackStack()
      }
    }

在ViewModel中

fun navigate(directions: NavDirections) {
  navigationCommands.postValue(NavigationCommand.To(directions))
}

从ViewModel导航

navigate(FragmentADirections.actionToFragmentB())

这只是一种方法,您可以检查此Using Navigation Architecture Component in a large banking app。 它对从视图模型导航和从片段中删除样板代码有很好的解释。