0

所以我使用LiveData和ViewModel来设置获取和插入数据的功能,我使用Room数据库来保存数据。

在我将数据插入数据库后,我的 RecyclerView 没有更新数据。

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)
        }

    }
}
}

使用 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()
    }

}

使用 LiveData 的 ViewModel 类

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)
        }
    }
}

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)
}

将数据插入数据库的活动

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()
    }

我不知道这是什么问题,我卡了2天。

提前致谢。

4

1 回答 1

1

如果您使用单例实现,则需要检查您的数据库实例。我遇到了同样的问题,然后我在代码中发现了错误,我的解决方案从下面的代码中更改为单例`

companion object {
    private var INSTANCE: PokemonDatabase? = null

    fun getDatabase(context: Context): PokemonDatabase {
        return INSTANCE ?: Room.databaseBuilder(
            context.applicationContext,
            PokemonDatabase::class.java,
            "pokemon_db"
        ).build()
    }

`

到下面的代码

companion object {
    @Volatile
    private var INSTANCE: PokemonDatabase? = null
    fun getDatabase(context: Context): PokemonDatabase {
        return INSTANCE ?: synchronized(this) {
            val instance = Room.databaseBuilder(
                context.applicationContext,
                PokemonDatabase::class.java,
                "pokemon_db"
            ).build()
            INSTANCE = instance
            instance//this return instance
        }
    }
}
于 2020-12-12T05:24:58.400 回答