NavArgs 返回 RuntimeException

NavArgs returning a RuntimeException

NavArgs 没有 returning 一个值,当我尝试通过更新片段中的 setOnClickListener 进行更新时,我才得到这个值:

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException



Caused by: java.lang.IllegalArgumentException: Required argument "currentAlarm" is missing and does not have an android:defaultValue

我需要 return 在 RecyclerView 中选择的警报的 ID,因此默认值在这里没有意义。

NavArgs 在导航视图中正确设置,没有默认值。 model 和 ID 会不会用 autoGenerate 设置错了?还是通过适配器进行这里的问题?

更新片段:

class UpdateFragment : Fragment() {

private val timePickerUtil = TimePickerUtil()
lateinit var binding: FragmentUpdateBinding
private lateinit var alarmViewModel: AlarmViewModel
private val args by navArgs<UpdateFragmentArgs>()

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    binding = FragmentUpdateBinding.inflate(inflater, container, false)

    alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java]

    binding.fragmentBtnUpdateAlarm.setOnClickListener {
        updateAlarm()
        Navigation.findNavController(requireView())
            .navigate(R.id.action_updateFragment_to_homeFragment)
    }
    return binding.root
}

private fun updateDatabase(id: Int, hour: Int, minute: Int, repeat: Boolean) {
    val alarm = Alarm(id, hour, minute, repeat)
    alarmViewModel.update(alarm)
}

private fun updateAlarm() {
    val timePicker = binding.fragmentUpdateAlarmTimePicker
    val id = args.currentAlarm.id
    val hour = timePickerUtil.getTimePickerHour(timePicker)
    val minute = timePickerUtil.getTimePickerMinute(timePicker)
    val repeat = binding.fragmentUpdateAlarmRecurring.isChecked

    val alarmManager = AlarmManager(
        id,
        hour,
        minute,
        true,
        binding.fragmentUpdateAlarmRecurring.isChecked
    )

    updateDatabase(id, hour, minute, repeat)
    alarmManager.cancel(requireContext())
    alarmManager.schedule(requireContext())
}

}

适配器:

class AlarmListAdapter() :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {

class MyViewHolder(binding: LayoutAlarmBinding) : RecyclerView.ViewHolder(binding.root)

private var alarmList = ArrayList<Alarm>()


private var onItemClickListener: OnItemClickListener? = null

interface OnItemClickListener{
    fun onClick(alarm: Alarm)
    fun onLongClick(alarm: Alarm)
}

fun setOnItemClickListener(listener: OnItemClickListener){
    onItemClickListener = listener
}


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    val binding = LayoutAlarmBinding.inflate(LayoutInflater.from(parent.context))
    return MyViewHolder(binding)
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    val currentItem = alarmList[position]
    val minute = currentItem.minute
    holder.itemView.findViewById<TextView>(R.id.tv_alarm_time).text =
        if (minute >= 10) {
            "${currentItem.hour}:${currentItem.minute}"
        } else {
            "${currentItem.hour}:0${currentItem.minute}"
        }

    holder.itemView.setOnClickListener{
        if(onItemClickListener != null){
            onItemClickListener?.onClick(currentItem)
        }
    }

    holder.itemView.setOnLongClickListener {
        if(onItemClickListener != null){
            onItemClickListener?.onLongClick(currentItem)
        }
        true
    }
}

override fun getItemCount(): Int {
    return alarmList.size
}

fun setData(alarm: List<Alarm>) {
    alarmList.clear()
    alarmList.addAll(alarm)
    notifyDataSetChanged()
}

}

主页片段:

class HomeFragment : Fragment() {

lateinit var binding: FragmentHomeBinding
private lateinit var alarmViewModel: AlarmViewModel

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    binding = FragmentHomeBinding.inflate(inflater, container, false)

    // RecyclerView
    val adapter = AlarmListAdapter()
    val recyclerView = binding.recyclerView
    recyclerView.adapter = adapter
    recyclerView.layoutManager = LinearLayoutManager(requireContext())

    //ViewModel
    alarmViewModel = ViewModelProvider(this).get(AlarmViewModel::class.java)
    alarmViewModel.readAlarmData.observe(viewLifecycleOwner, Observer { alarm ->
        adapter.setData(alarm)
    })

    binding.btnAddAlarm.setOnClickListener {
        Navigation.findNavController(requireView())
            .navigate(R.id.action_homeFragment_to_newAlarmFragment)
    }

    adapter.setOnItemClickListener(object : AlarmListAdapter.OnItemClickListener {

        override fun onClick(alarm: Alarm) {
            Navigation.findNavController(requireView())
                .navigate(R.id.action_homeFragment_to_updateFragment)
        }

        override fun onLongClick(alarm: Alarm) {
            val deleteBuilder = AlertDialog.Builder(requireContext())
            deleteBuilder.setPositiveButton("Delete") { _, _ ->
                alarmViewModel.delete(alarm)
                Toast.makeText(context, "Alarm Deleted", Toast.LENGTH_SHORT)
                    .show()
            }
            deleteBuilder.setNegativeButton("Cancel") { _, _ ->

            }
            deleteBuilder.setTitle("Delete Alarm?")
            deleteBuilder.create().show()
        }
    })

    return binding.root
}

}

我的闹钟型号:

@Parcelize
@Entity(tableName = "alarm_table")
data class Alarm(
    @PrimaryKey(autoGenerate = true)
    val id: Int,
    val hour: Int,
    val minute: Int,
    val repeat: Boolean
): Parcelable

Safe args 创建自己的 类(就像这里的 HomeFragmentDirections)。因此,在 homeFragment 中,您要为适配器设置 onclick 侦听器,您应该使用->

adapter.setOnItemClickListener(object : AlarmListAdapter.OnItemClickListener {

        override fun onClick(alarm: Alarm) {
            Navigation.findNavController(requireView())
                .navigate(HomeFragmentDirections.actionHomeFragmentToUpdateFragment(params))
        }

        override fun onLongClick(alarm: Alarm) {
            // preform longclick action here
        }
    })

并在相应导航图中的UpdateFragment中添加所需类型的参数(在您的情况下,id可能是int或String类型)。

我希望你明白我的意思,如果没有,请不要犹豫发表评论。 您可以在 android 开发者网站 here.

上阅读相关内容