【问题标题】:Navigating with safeArgs in Kotlin throws and error在 Kotlin 中使用 safeArgs 导航抛出和错误
【发布时间】:2020-12-12 14:42:54
【问题描述】:

我有一个片段,可以通过底部导航栏导航到不带参数的导航栏,也可以从带有参数的不同片段导航到。导航本身工作得很好,但是一旦我添加了我的参数,它就会崩溃。

我不确定需要多少代码,如果不完整,请见谅:

这是我的导航片段:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/navigation"
app:startDestination="@id/homeFragment">

<fragment
    android:id="@+id/homeFragment"
    android:name="fh.wfp2.flatlife.ui.views.HomeFragment"
    android:label="Flatlife"
    tools:layout="@layout/home_fragment" />
<fragment
    android:id="@+id/todoFragment"
    android:name="fh.wfp2.flatlife.ui.views.TodoFragment"
    android:label="Todos">
    <action
        android:id="@+id/action_todoFragment_to_addTodoFragment"
        app:destination="@id/addTodoFragment" />
    <argument
        android:name="taskname"
        app:argType="string" />
    <argument
        android:name="isImportant"
        app:argType="boolean" />
</fragment>
<fragment
    android:id="@+id/addTodoFragment"
    android:name="fh.wfp2.flatlife.ui.views.AddTodoFragment"
    android:label="AddTodoFragment">
    <action
        android:id="@+id/action_addTodoFragment_to_todoFragment"
        app:destination="@id/todoFragment" />


</fragment>
</navigation>

这是我的addTodoFragment

class AddTodoFragment : Fragment(R.layout.add_task_fragment) {

private lateinit var binding: AddTaskFragmentBinding

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
 
    binding = AddTaskFragmentBinding.bind(view)
    binding.bAddTodo.setOnClickListener {
        if (binding.etAddTodo.text.isNotEmpty()) {
           // viewModel.onAddTodoClicked(binding.etAddTodo.text.toString(), 
binding.cbImportant.isChecked)
           findNavController().navigate(
                AddTodoFragmentDirections.actionAddTodoFragmentToTodoFragment(
                    binding.etAddTodo.text.toString(), binding.cbImportant.isChecked
                )
            )
        } else {
            Snackbar.make(it, "The task field can't be empty", Snackbar.LENGTH_SHORT).show()
            
        }
    }

}
}

这就是我试图在 TodoFragment 中获取参数的方式。

private val args: TodoFragmentArgs by navArgs()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
//setting binding and other onClickListeners but they work fine

//reading args
//this i thought would work because then args only get read if not null
args?.let { //debugger stops here and app crashes
        if(args.taskname.isNotEmpty())
        viewModel.onAddTodoClick(Todo(name = args.taskname, isImportant = args.isImportant))
    }

/*second try which I took directly from developers.android but which doesn't make sense in my case i 
think because the args could be null I guess

val todoName = args.taskname
    val isImportant = args.isImportant
    viewModel.onAddTodoClick(Todo(name = todoName, isImportant = isImportant))
*/

}

这是我收到的错误消息:

我希望我的意思很清楚,否则,我会更新问题。这可能是一些简单的事情,但我不能完全确定它。

【问题讨论】:

  • “只有在不传递参数的情况下导航到 TodoFragment” 我不明白这怎么可能。代码无法编译,因为该操作需要 2 个参数。
  • @Onik 引用的操作在没有任何参数的情况下不会在场景中导航。不带参数导航时,我从 HomeFragment -> TodoFragment(底部导航)导航时,我从 AddTodoFragment -> TodoFragment 导航。
  • 我相信这就是问题所在。当底部导航时调用args?.let 时,args 正在被延迟初始化并抛出异常。
  • @Onik 嗯好的。但是随着下面答案中 PiyushMaheswari 的变化,它应该可以工作,对吧?因为我猜它会立即初始化?我会再试一次,但遗憾的是它之前没有用。
  • @Onik 谢谢!!这对我有用!我还有其他一些关于逻辑的问题,但你的小费解决了这个问题。非常感谢!如果您想制定一个答案,我会接受它,否则我会更新我的问题或发布答案并给予您信任。你知道为什么这行得通吗?或者说得更好:为什么 TodoFragmentArgs 不行?

标签: android kotlin android-safe-args


【解决方案1】:

感谢@Onik 让 SafeArgs 离开的想法。我需要转储 SafeArgs 类调用以 接收 参数,现在看起来像这样。这绝对不是我猜想的最干净的方式,但我还不知道为什么 SafeArgs 调用不起作用,而且我对 Kotlin 太陌生,无法以更干净的方式编写以下代码。但它现在有效。

arguments?.let {
        var myArg1: String? = null
        var myArg2: Boolean
        arguments?.getString("argument1")?.let { arg1->
            myArg1= arg1
        }
        arguments?.getBoolean("argument2")?.let { arg2->
            myArg2= arg2

            if (myArg1!= null)
                //do logis with args
        }

    }

【讨论】:

    【解决方案2】:
    val args = arguments?.let {
        SecondFragmentArgs.fromBundle(
            it
        )
    }
    if (args != null) {
        firstDataList = args.taskName
        secondDataList = args.isImportant
    }
    

    这就是接收片段代码的样子。这应该可以。

    【讨论】:

    • findNavController().navigate(FirstFragmentDirections.actionFirstFragmentToSecondFragment(taskName, isImporatant)
    • 我试过这个,但这不起作用。我仍然得到相同的错误代码。 (我会更新帖子,让错误代码可见)
    • 是的,我做到了。我使用绑定,但语法与我使用的相同。该应用程序在导航到没有设置参数的片段时崩溃,所以我什至无法到达发送参数的片段,如果这有意义的话。
    • 那我猜绑定逻辑可能是罪魁祸首。
    • 我不这么认为,因为我什至还没有导航到那个片段。如果我省略了参数的接收代码,我可以很好地导航。只有在不传递参数的情况下导航到 TodoFragment 时。
    猜你喜欢
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-16
    相关资源
    最近更新 更多