so I'm using LiveData and ViewModel to set the function of getting and insert the data, and I'm using the Room database to save the data.
after I inserting the data to the database my RecyclerView not updating the data.
RecyclerAdapterTransaksi.kt
class RecyclerAdapterTransaksi(var context: Context, private val listener: (Transaksi) -> Unit) :
RecyclerView.Adapter<RecyclerAdapterTransaksi.TransaksiViewHolder>() {
private var listTransaksi = arrayListOf<Transaksi>()
fun setListTransaksi(listTransaksi: ArrayList<Transaksi>) {
this.listTransaksi = listTransaksi
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransaksiViewHolder {
context = parent.context
val binding = ListItemBinding.inflate(LayoutInflater.from(context), parent, false)
return TransaksiViewHolder(binding)
}
override fun onBindViewHolder(holder: TransaksiViewHolder, position: Int) {
holder.bindItem(listTransaksi[position], listener)
}
override fun getItemCount(): Int = listTransaksi.size
class TransaksiViewHolder(private val binding: ListItemBinding) :
RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SimpleDateFormat")
fun bindItem(transaksi: Transaksi, listener: (Transaksi) -> Unit) {
binding.textViewNamaTransaksi.text = transaksi.namaTransaksi
binding.textViewJmlTransaksi.text = transaksi.total.toString()
binding.textViewTglTransaksi.text = SimpleDateFormat("dd MMM yyyy").format(transaksi.tglTransaksi!!)
itemView.setOnClickListener {
listener(transaksi)
}
}
}
}
The fragment that shows data from the database using RecyclerView
PemasukkanFragment.kt
class PemasukkanFragment : Fragment() {
private var _binding: FragmentPemasukkanBinding? = null
private val binding get() = _binding!!
private val viewModel: TransaksiViewModel by lazy {
val dataSource = UwangkuDatabase.getInstance(requireContext()).transactionDao
val factory = TransaksiViewModelFactory(dataSource)
ViewModelProvider(this, factory).get(TransaksiViewModel::class.java)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentPemasukkanBinding.inflate(inflater, container, false)
binding.fabPemasukkan.setOnClickListener {
val intent = Intent(requireContext(), TambahDataActivity::class.java)
intent.putExtra(Constant.TIPE_TRANSAKSI, Constant.PEMASUKKAN)
intent.putExtra(Constant.TIPE_AKSI, Constant.AKSI_TAMBAH)
startActivity(intent)
}
getDataPemasukkan()
return binding.root
}
private fun getDataPemasukkan() {
binding.recyclerViewPemasukan.setHasFixedSize(true)
binding.recyclerViewPemasukan.layoutManager = LinearLayoutManager(requireContext())
val adapter = RecyclerAdapterTransaksi(requireContext()) {
//action when item clicked
showKonfirmasiEdit(it)
}
binding.recyclerViewPemasukan.adapter = adapter
viewModel.getData(Date(), Constant.PEMASUKKAN)
viewModel.dataTransaksi.observe(viewLifecycleOwner, Observer {
adapter.setListTransaksi(it as ArrayList<Transaksi>)
})
}
private fun showKonfirmasiEdit(transaksi: Transaksi){
val intent = Intent(requireContext(),TambahDataActivity::class.java)
val builder = AlertDialog.Builder(requireContext())
.setMessage(R.string.edit_message)
.setPositiveButton(R.string.edit){_,_ ->
intent.putExtra(Constant.DATA_PEMASUKKAN, transaksi)
intent.putExtra(Constant.TIPE_TRANSAKSI, Constant.PEMASUKKAN)
intent.putExtra(Constant.TIPE_AKSI, Constant.AKSI_EDIT)
startActivity(intent)
}
.setNegativeButton(R.string.batal){dialog, _ ->
dialog.cancel()
}
builder.show()
}
}
The ViewModel class that used LiveData
TransaksiViewModel.kt
class TransaksiViewModel(private val dao: TransaksiDao) : ViewModel() {
private var _dataTransaksi = MutableLiveData<List<Transaksi>>()
val dataTransaksi: LiveData<List<Transaksi>>
get() = _dataTransaksi
private suspend fun getDataTransaksi(tgl : Date, tipe : String) = withContext(Dispatchers.IO) {
dao.getData(tgl, tipe)
}
fun getData(tgl : Date, tipe : String) {
viewModelScope.launch {
_dataTransaksi.postValue(getDataTransaksi(tgl, tipe))
}
}
fun inserDataTransaksi(transaksi: Transaksi) {
viewModelScope.launch {
insertTransaksi(transaksi)
}
}
private suspend fun insertTransaksi(transaksi: Transaksi){
withContext(Dispatchers.IO) {
dao.insertDataTransaksi(transaksi)
}
}
fun updateDataTransaksi(transaksi: Transaksi){
viewModelScope.launch {
updateTransaksi(transaksi)
}
}
private suspend fun updateTransaksi(transaksi: Transaksi){
withContext(Dispatchers.IO){
dao.updateDataTransaksi(transaksi)
}
}
}
The DAO
TransakiDao.kt
@Dao
interface TransaksiDao {
@Insert
fun insertDataTransaksi(transaksi: Transaksi)
@Query("SELECT * FROM transaksi WHERE datetime(tanggal/1000,'unixepoch','start of month') = datetime(:tgl/1000,'unixepoch','start of month') AND jenis = :tipe ORDER BY id DESC")
fun getData(tgl : Date, tipe : String): List<Transaksi>
@Update
fun updateDataTransaksi(transaksi: Transaksi)
}
The activity for inserting data to database
TambahDataActivity.kt
class TambahDataActivity : AppCompatActivity() {
private lateinit var binding: ActivityTambahDataBinding
private val viewModel: TransaksiViewModel by lazy {
val dataSource = UwangkuDatabase.getInstance(this).transactionDao
val factory = TransaksiViewModelFactory(dataSource)
ViewModelProvider(this, factory).get(TransaksiViewModel::class.java)
}
@SuppressLint("SimpleDateFormat")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTambahDataBinding.inflate(layoutInflater)
setContentView(binding.root)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
val getAksi = intent.getStringExtra(Constant.TIPE_AKSI)
val getJenisTransaksi = intent.getStringExtra(Constant.TIPE_TRANSAKSI)
if(getJenisTransaksi == Constant.PEMASUKKAN){
val dataPemasukan = intent.getParcelableExtra<Transaksi>(Constant.DATA_PEMASUKKAN)
if(dataPemasukan != null){
getDataFromIntent(dataPemasukan)
}
} else if(getJenisTransaksi == Constant.PENGELUARAN){
val dataPengeluaran = intent.getParcelableExtra<Transaksi>(Constant.DATA_PENGELUARAN)
if(dataPengeluaran != null){
getDataFromIntent(dataPengeluaran)
}
}
if(getAksi == Constant.AKSI_EDIT){
binding.buttonTambah.text = getString(R.string.edit)
title = getString(R.string.edit_data)
}
binding.textViewTanggal.setOnClickListener { showDatePickerDialog() }
binding.buttonTambah.setOnClickListener {
if(getAksi == Constant.AKSI_TAMBAH){
insertData()
}else if(getAksi == Constant.AKSI_EDIT){
updateData()
}
}
}
@SuppressLint("SimpleDateFormat")
private fun insertData(){
val namaTransaksi = binding.editTextKeterangan.text
val jumlahTransaki = binding.editTextJumlah.text
val getJenisTransaksi = intent.getStringExtra(Constant.TIPE_TRANSAKSI)
val jenisTransaksi = if (getJenisTransaksi == Constant.PEMASUKKAN) {
Constant.PEMASUKKAN
} else {
Constant.PENGELUARAN
}
val tanggalTransaksi =
SimpleDateFormat("dd-MM-yyyy").parse(binding.textViewTanggal.text.toString())
val transaksi = Transaksi(
0,
namaTransaksi.toString(),
jenisTransaksi,
jumlahTransaki.toString().toInt(),
tanggalTransaksi
)
viewModel.inserDataTransaksi(transaksi).apply { finish() }
}
@SuppressLint("SimpleDateFormat")
private fun updateData(){
val namaTransaksi = binding.editTextKeterangan.text
val jumlahTransaki = binding.editTextJumlah.text
val getJenisTransaksi = intent.getStringExtra(Constant.TIPE_TRANSAKSI)
val jenisTransaksi = if (getJenisTransaksi == Constant.PEMASUKKAN) {
Constant.PEMASUKKAN
} else {
Constant.PENGELUARAN
}
val tanggalTransaksi =
SimpleDateFormat("dd-MM-yyyy").parse(binding.textViewTanggal.text.toString())
if(getJenisTransaksi == Constant.PEMASUKKAN){
val dataPemasukan = intent.getParcelableExtra<Transaksi>(Constant.DATA_PEMASUKKAN)!!
val transaksi = Transaksi(dataPemasukan.id,
namaTransaksi.toString(),
jenisTransaksi,
jumlahTransaki.toString().toInt(),
tanggalTransaksi
)
viewModel.updateDataTransaksi(transaksi)
} else if(getJenisTransaksi == Constant.PENGELUARAN){
val dataPengeluaran = intent.getParcelableExtra<Transaksi>(Constant.DATA_PENGELUARAN)!!
val transaksi = Transaksi(dataPengeluaran.id,
namaTransaksi.toString(),
jenisTransaksi,
jumlahTransaki.toString().toInt(),
tanggalTransaksi
)
viewModel.updateDataTransaksi(transaksi)
}
}
@SuppressLint("SimpleDateFormat")
private fun getDataFromIntent(data : Transaksi?){
if(data != null){
binding.editTextKeterangan.setText(data.namaTransaksi)
binding.editTextJumlah.setText(data.total.toString())
binding.textViewTanggal.text = SimpleDateFormat("dd-MM-yyyy").format(data.tglTransaksi!!)
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> finish()
}
return true
}
@SuppressLint("SetTextI18n")
private fun showDatePickerDialog() {
val calendar = Calendar.getInstance()
val tahun = calendar.get(Calendar.YEAR)
val bulan = calendar.get(Calendar.MONTH)
val hari = calendar.get(Calendar.DAY_OF_MONTH)
val datePicker = DatePickerDialog(
this,
DatePickerDialog.OnDateSetListener { view, _year, monthOfYear, dayOfMonth ->
binding.textViewTanggal.text = "$dayOfMonth-${monthOfYear + 1}-$_year "
},
tahun,
bulan,
hari
)
datePicker.show()
}
I don't know what's the problem with this, I get stuck for 2 days.
Thanks in advance.
you need to check your database instance if you are using singleton implementation. I faced same with your issue then I found the bug in my code and my solution is changed singleton from below code`
`
to below code