【问题标题】:Trouble with NavController inside OnBackPressedCallbackOnBackPressedCallback 中的 NavController 出现问题
【发布时间】:2019-06-18 12:59:56
【问题描述】:

我在 OnBackPressedCallback 中收到 does not have a NavController set 错误。这是代码

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {

    fragmentView = inflater.inflate(R.layout.patient_info_fragment, container, false)

    if(Utils.connectedToInternet()){
        fragmentView.pastScreeningsButton.visibility = View.GONE
    }

    requireActivity().onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
                Navigation.findNavController(fragmentView).navigate(R.id.action_patientInfoFragment_to_patientsList)
        }
    })
    setHasOptionsMenu(true)


    return fragmentView
}

当我回到实现此功能的片段时,我只会收到此错误。

我的主页片段中有android:name="androidx.navigation.fragment.NavHostFragment"

为了澄清,我正在使用导航控制器围绕我的应用程序进行所有导航,它工作得很好。我只在这个OnBackPressedCallback 中得到这个错误,并且只有当用户导航回实现它的片段时。

如果您需要查看我的更多代码,请告诉我。

【问题讨论】:

  • 当我第一次膨胀片段布局时,我得到了片段视图。我正在使用完整的 onCreate() 更新代码。
  • 我不知道我需要执行 removeCallback。我把它放在哪里?

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


【解决方案1】:

您可能会遇到片段旧实例泄漏的问题。此外,将创建的视图存储在另一个变量(如fragmentView)中也不是一个好习惯。总而言之,您的 onCreateView 实现做了太多与其目的无关的事情。

我建议将功能拆分为相关的生命周期方法,并直接在回调中使用fragment.view。为了不遇到未附加视图的问题,您可以将回调与生命周期绑定和解除绑定。

class PatientInfoFragment: Fragment() {

    private val callback = object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            Navigation.findNavController(view).navigate(R.id.action_patientInfoFragment_to_patientsList)
        }
    }

    override fun onCreate(
        savedInstanceState: Bundle?
    ) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View = inflater.inflate(R.layout.patient_info_fragment, container, false)

    override fun onViewCreated(
        view: View,
        savedInstanceState: Bundle?
    ) {
        if(Utils.connectedToInternet()){
            view.pastScreeningsButton.visibility = View.GONE
        }
    }

    override fun onStart() {
        super.onStart()
        requireActivity().onBackPressedDispatcher.addCallback(callback)
    }

    override fun onStop() {
        callback.remove()
        super.onStop()
    }
}

回调生命周期绑定可以与片段绑定为生命周期所有者调用另一个addCallback(LifecycleOwner, OnBackPressedCallback)

此外,您还可以查看 Android KTXKotlin Android Extensions 以简化您的实施。

【讨论】:

  • 感谢您的详细回复。 removeCallback 不是一件事,很确定它会自动发生。您的其余答案是有道理的,我对我的代码进行了更改。再次感谢。
  • 您在 Navigation.findNavController(view) 中从哪里获得视图?
  • 视图来自片段。关于removeCallback(),您是对的,您必须致电callback.remove() 或改用addCallback(this, callback)
  • 对不起,我不明白。如何从全局片段中获取视图?
  • callback 应该是片段的属性。由于它也是一个内部类,它可以访问view
【解决方案2】:

将您的代码移动到onViewCreated 并传递由覆盖方法提供的view

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        requireActivity().onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
                Navigation.findNavController(view).navigate(R.id.action_patientInfoFragment_to_patientsList)
        }
    })
    }

如果这也不起作用,请将.navigate() 替换为popBastack(R.id.framgment_where_you_want to go, false),以防您之前的片段保留在backStack

【讨论】:

  • 您是否将您的片段包含在nav_graph
  • 是的,我有。首次加载片段时导航效果很好,只有当我导航回片段时才会出现此问题。
  • 您使用的是什么 xml 元素? <fragment/><FrameLayout\>
  • 使用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-05
  • 2011-09-23
  • 2020-08-23
相关资源
最近更新 更多