使用导航体系结构组件添加(而不是替换)片段

时间:2018-10-09 08:51:50

标签: android android-architecture-components android-architecture-navigation

我有一个包含产品列表片段和许多其他片段的活动,我正在尝试使用Architecture组件导航控制器。

问题是:它替换了(开始目标)产品列表片段,并且我不希望用户单击“后退”按钮时重新加载列表。

  

如何使片段事务作为添加而不是替换。

7 个答案:

答案 0 :(得分:3)

您必须重写NavHostFragment的createFragmentNavigator方法并返回YourFragmentNavigator

YourFragmentNavigator必须覆盖FragmentNavigator的navigate方法。

将FragmentNavigator的navigate方法复制并粘贴到您的YourFragmentNavigator中。

在导航方法中,用

更改行ft.replace(mContainerId, frag);
if (fragmentManager.fragments.size <= 0) {
    ft.replace(containerId, frag)
} else {
    ft.hide(fragmentManager.fragments[fragmentManager.fragments.size - 1])
    ft.add(containerId, frag)
}

解决方案如下:

class YourNavHostFragment : NavHostFragment() {
override fun createFragmentNavigator(): Navigator<...> {
    return YourFragmentNavigator(...)
}}

....

class YourFragmentNavigator(...) : FragmentNavigator(...) {

override fun navigate(...){
    ....
    if (fragmentManager.fragments.size <= 0) {
        ft.replace(containerId, frag)
    } else {
        ft.hide(fragmentManager.fragments[fragmentManager.fragments.size - 1])
        ft.add(containerId, frag)
     }
     ....
}}

在您的xml中使用YourNavHostFragment

答案 1 :(得分:1)

只需复制 FragmentNavigator 的代码(300 行)并将 replace() 替换为 add()。这是目前对我来说最好的解决方案。

@Navigator.Name("fragment")
public class CustomFragmentNavigator extends 
Navigator<...> {
    ...

    public NavDestination navigate(...) {
        ...
        ft.add(mContainerId, frag);
        ...
    }

    ...
}

答案 2 :(得分:0)

稍作搜索后,这是不可能的,但是问题本身可以通过viewmodel和livedata或rxjava解决。 因此,碎片状态会在交易后保留,并且我的产品列表不会每次都重新加载

答案 3 :(得分:0)

我在等待add和片段事务的其他选项时遇到了同样的问题,我实施了这项工作来保留回弹时的状态。

我刚刚添加了一个检查是否存在绑定,然后我恢复了先前的状态,与网络调用相同,我添加了一个检查视图模型中是否存在数据,然后不进行网络重新提取。经过测试后,它可以按预期工作。

  private lateinit var binding: FragmentSearchResultsBinding

  override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        viewModel =
            ViewModelProviders.of(this, mViewModelFactory).get(SearchResultsViewModel::class.java)
        return if (::binding.isInitialized) {
            binding.root
        } else {
            binding = DataBindingUtil.inflate(inflater, R.layout.fragment_search_results, container, false)

            with(binding) {
               //some stuff
                root
            }
        }
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //reload only if search results are empty
        if (viewModel.searchResults.isEmpty()) {
           args.searchKey.let {
                binding.toolbarHome.title = it
                viewModel.onSearchResultRequest(it)
            }
        }
    }

答案 4 :(得分:0)

@Rainmaker在我看来是正确的,我做了同样的事情。 我们还可以将回收者视图的位置/状态保存在onSaveInstanceState中 以便在导航回列表片段时返回到相同的回收者视图位置。

答案 5 :(得分:0)

Android导航组件只是替换,但您想添加片段而不是像对话框那样替换,您可以使用它,但需要最小化。 “ Version 2.1.0 ”作为导航组件。

Solution

,您会看到“ Dialog destinations

答案 6 :(得分:0)

我遇到了同样的问题,但就我而言,我更新了代码以使用livedata和viewmodel。 当您按回时,不会再次创建视图模型,因此您的数据得以保留。

确保您在viewmodel的init方法中进行了api调用,以便在创建viewmodel时仅发生一次