虽然 JetPack 的导航组件看起来很有前途,但我却找不到实现我想要的东西的方法。
让我们看一下示例应用程序屏幕:
该应用程序有一个主要活动、一个顶部工具栏、一个带有 fab 的底部工具栏。
我面临着两个挑战,我想以正确的方式解决它们。
1. 我需要实现片段事务,以便允许根据用户交互替换屏幕上的片段。我可以想到并实施三种方法:
- 回调方式。有接口
onFragmentAction
片段中的回调并让活动实现它。所以基本上当用户按下按钮时FragmentA
我可以打电话onFragmentAction
使用参数,以便活动将触发并启动例如事务以将其替换为FragmentB
- 实施
Navigation
来自 JetPack 的组件。虽然我已经尝试过并且看起来非常简单,但我遇到了无法检索当前片段的问题。
- 使用共享的
ViewModel
在fragment和activity之间,从fragment中更新它并在activity中观察它。这将是回调的“替代”
2. 自FAB
在父活动中,当按下时,我需要能够与当前可见片段进行交互并执行操作。例如,在片段内的回收器视图中添加一个新项目。所以基本上是 Activity 和 Fragment 之间进行通信的一种方式我可以想到有两种方法可以做到这一点
- 如果不使用
Navigation
那么我可以使用findFragmentById
并检索当前片段并运行公共方法来触发操作。
- 在片段和活动之间使用共享的“ViewMode”,从活动更新它并在片段中观察它。
因此,正如您所看到的,推荐的导航方法是使用新的“导航”架构组件,但是,目前它缺乏检索当前片段实例的方法,因此我不知道如何在活动和片段。
这可以通过以下方式实现shared ViewModel
但这里我有一个缺失的部分:我知道片段到片段的通信可以通过共享 ViewModel 进行。我认为当片段有一些共同点时这是有意义的,例如主/详细场景并且共享相同的视图模型非常有用。
但是,然后在活动和ALL碎片,怎么可能共享ViewModel
使用?每个片段都需要它自己的复杂ViewModel。难道它是一个GeneralViewModel
它在活动和所有片段中与常规片段视图模型一起实例化,因此每个片段中有 2 个视图模型。
能够使用视图模型在片段和活动之间进行对话将使得不需要查找活动片段,因为视图模型将提供所需的机制并且还允许使用Navigation
成分。
很高兴收到任何信息。
稍后编辑。这是基于下面评论的一些示例代码。这是我的问题的解决方案吗?这可以处理片段和父活动之间的更改吗?这是推荐的。
private class GlobalViewModel ():ViewModel(){
var eventFromActivity:MutableLiveData<Event>
var eventFromFragment:MutableLiveData<Event>
fun setEventFromActivity(event:Event){
eventFromActivity.value = event
}
fun setEventFromFragment(event:Event){
eventFromFragment.value = event
}
}
然后在我的活动中
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)
}
}
然后在所有片段中都有这样的东西
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)
}
}