Parece que mi lista no se inicializa y no estoy muy seguro de lo que debería hacer aquí, cada vez que ejecuto obtengo:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.alarmclockproject, PID: 13493 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference at com.example.alarmclockproject.fragments.AlarmListAdapter.onBindViewHolder(AlarmListAdapter.kt:27)La eliminación de la notificaciónDataSetChanged () detiene el bloqueo fatal, pero luego no muestra alarmas en el fragmento, a pesar de que hay varios en la base de datos (verificado con DB Browser)
Aquí está mi adaptador:
class AlarmListAdapter() : RecyclerView.Adapter<RecyclerView.ViewHolder>() { private var alarmList: List<Alarm> = ArrayList() class ViewHolder(binding: FragmentHomeBinding) : RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val binding = FragmentHomeBinding.inflate(LayoutInflater.from(parent.context)) return ViewHolder(binding) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { val currentItem = alarmList[position] holder.itemView.findViewById<TextView>(R.id.tv_alarm_time).text = "${currentItem.hour}:${currentItem.minute}" //holder.itemView.findViewById<TextView>(R.id.tv_repeat_days) } override fun getItemCount(): Int { return alarmList.size } fun setData(alarm: List<Alarm>){ this.alarmList = alarm notifyDataSetChanged() } }My HomeFragment donde se muestra la vista del reciclador:
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) } return binding.root } }y su diseño:
<androidx.constraintlayout.widget.ConstraintLayout 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/frameLayout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".fragments.HomeFragment"> <TextView android:id="@+id/tv_next_alarm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="64dp" android:text="11:11" android:textAppearance="@style/TextAppearance.AppCompat.Display3" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/btn_add_alarm" android:layout_width="57dp" android:layout_height="57dp" android:layout_marginBottom="52dp" android:background="@drawable/round_button" android:text="+" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="411dp" android:layout_height="446dp" android:layout_marginStart="1dp" android:layout_marginTop="1dp" android:layout_marginEnd="1dp" android:layout_marginBottom="1dp" app:layout_constraintBottom_toTopOf="@+id/btn_add_alarm" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_next_alarm" /> </androidx.constraintlayout.widget.ConstraintLayout>Ver modelo:
class AlarmViewModel(application: Application) : AndroidViewModel(application) { val readAlarmData: LiveData<List<Alarm>> private val repository: AlarmRepository init { val alarmDao = AlarmsDatabase.getDatabase(application).alarmDao() repository = AlarmRepository(alarmDao) readAlarmData = repository.readAlarmData } fun addAlarm(alarm: Alarm) { viewModelScope.launch(Dispatchers.IO) { repository.addAlarm(alarm) } } }dao:
@Dao interface AlarmDao { @Insert() suspend fun addAlarm(alarm: Alarm) @Query("SELECT * FROM alarm_table ORDER BY id ASC") fun readAlarmData(): LiveData<List<Alarm>> @Update fun updateAlarm(alarm: Alarm) }y la clase de alarma:
@Entity(tableName = "alarm_table") data class Alarm ( @PrimaryKey(autoGenerate = true) val id: Int, val hour: Int, val minute: Int, val repeat: Boolean )La siguiente línea en onCreateViewHolder() está causando el bloqueo:
val binding = FragmentHomeBinding.inflate(LayoutInflater.from(parent.context))
Está inflando FragmentHomeBinding , que no tiene TextView con id R.id.tv_alarm_time . Use el del elemento RecyclerView en su lugar.