共享的ViewModel有助于片段和父级活动之间的通信

Ali*_*lin 5 android android-livedata android-viewmodel android-architecture-components android-jetpack

尽管JetPack的Navigation组件看起来很有前途,但是我到了一个找不到实现我想要的东西的地方。

让我们看一个示例应用程序屏幕:

该应用程序有一个主要活动,一个顶部的工具栏,一个底部的工具栏,并带有fab。我面临着2个挑战,我想让它们以正确的方式进行。

1.我需要实现片段事务,以便允许基于用户交互来替换屏幕上的片段。 我可以想到并实现三种方法:

  • 回调方式。onFragmentAction在片段中有一个接口回调,并有活动来实现它。因此,基本上,当用户按下按钮时,FragmentA我可以onFragmentAction使用params 进行调用,以便该活动将触发并开始执行例如将其替换为的交易FragmentB
  • Navigation从JetPack 实现组件。虽然我已经尝试过了,而且看起来很简单,但是由于无法检索当前片段,我遇到了一个问题。
  • ViewModel在片段和活动之间使用共享,从片段更新它并在活动中观察它。这将是回调的“替代”

2.由于FAB处于父活动中,因此在按下时,我需要能够与当前可见片段进行交互并执行操作。例如,在片段内的recyclerview中添加新项目。所以基本上是在活动和片段之间进行交流的一种 方式。我可以想到两种方式

  • 如果不使用,Navigation那么我可以使用findFragmentById并检索当前片段,并运行一个公共方法来触发操作。
  • 在片段和活动之间使用共享的“ ViewMode”,从活动中对其进行更新并在片段中进行观察。

因此,如您所见,推荐的导航方式是使用新的“ Navigation”架构组件,但是,目前它缺少检索当前片段实例的方法,因此我不知道如何在活动和片段。这可以通过以下方式实现,shared ViewModel但在这里我有一个遗漏的地方:我知道可以使用共享的ViewModel进行片段对片段的通信。我认为,当片段对此有一些共同点时(例如主/细节方案)并共享相同的视图模型,这很有用。

但是,然后在活动和所有片段之间进行交谈,如何使用共享ViewModel?每个片段都需要自己的复杂ViewModel。可能是GeneralViewModel在活动和所有片段中实例化的a ,以及常规片段视图模型,因此每个片段中都有2个视图模型。

能够通过视图模型在片段和活动之间进行交谈将使不需要主动片段的发现成为可能,因为视图模型将提供所需的机制,并且还将允许使用Navigation组件。

很高兴收到任何信息。

以后编辑。这是一些基于注释的示例代码。这是我的问题的解决方案吗?这可以处理片段和父级活动之间的更改吗,这是建议的方面。

 private GlobalViewModel ():ViewModel(){

      var eventFromActivity:MutableLiveData<Event>
      var eventFromFragment:MutableLiveData<Event>


      fun setEventFromActivity(event:Event){
          eventFromActivity.value = event
      }

      fun setEventFromFragment(event:Event){
          eventFromFragment.value = event
      }

 } 
Run Code Online (Sandbox Code Playgroud)

然后在我的活动中

class HomeActivity: AppCompatActivity(){

   onCreate{
       viewModel = ViewModelProviders.of(this, factory)
                .get(GlobalViewModel::class.java)

        viewModel.eventsFromFragment.observe(){
           //based on the Event values, could update toolbar title, could start
           // new fragment, could show a dialog or snackbar
        ....
        }   

     //when need to update the fragment do 
     viewModel.setEventFromActivity(event)
   }
}
Run Code Online (Sandbox Code Playgroud)

然后在所有片段中都有这样的内容

class FragmentA:Fragment(){

  onViewCreated(){

       viewModel = ViewModelProviders.of(this, factory)
                .get(GlobalViewModel::class.java)

        viewModel.eventsFromActivity.observe(){
           // based on Event value, trigger a fun from the fragment 
        ....
        }

        viewModelFragment = ViewModelProviders.of(this, factory)
            .get(FragmentAViewModel::class.java)

        viewModelFragment.some.observe(){
        ....
        }   

  //when need to update the activity do 
     viewModel.setEventFromFragment(event)      
  }

}
Run Code Online (Sandbox Code Playgroud)