因此,我使用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显示数据库数据的片段
Pemasukkanframent。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)
}
}
}
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)
}
将数据插入数据库的活动
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()
}
我不知道这有什么问题,我被困了两天。
提前谢谢。
如果使用单例实现,则需要检查数据库实例。我面临着同样的问题,然后我发现了错误,在我的代码和我的解决方案是改变单从下面的代码
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
}
}
}
我试图解决一个问题,但没有成功。每当数据库(数据库室)中特定模型的记录发生变化时,我想更新我的回收器视图。我使用ViewModel来处理模型数据,记录列表存储在LiveData中。 数据库 模型 刀 视图模型 碎片 现在,我的问题是为什么观察者只被调用一次(在片段的开始),然后没有被再次调用?我如何让观察者不断地倾听数据库中的变化(插入,更新,删除),以便我的回收器视图可以立即更新?非常感谢任何建
活动可以按以下方式访问此列表: 我的问题是,我要这样做: > 在函数中,我异步获取数据,首先检查数据库(房间)中的数据
我试图在下面的代码中找出,为什么当我用新数据填充数据库时,Room的LiveData observable没有给我新的班次。 这是放在我的activity的onCreate方法上的: 这是populateAdapter方法: 我还有以下填充数据库的代码(我使用RxJava在IO线程上完成这项工作,因为Room需要在主线程之外调用它的代码): 当我开始观察ShiftsViewModel之后调用per
我有一个ViewModel,我正在使用LiveData,所以我有一个返回LiveData>的DAO,我可以让它工作,但实际上我希望它首先显示来自Room数据库的数据(如果有的话),然后当webservice返回新数据(如果有的话)时,将其写入数据库,然后用数据库中的最新数据更新ViewModel。我首先从数据库返回数据,并在后台将新数据写入数据库,但如何让ViewModel再次使用数据库中的新数据
UserViewModel: 用户存储库:
我的应用程序使用MVVM架构。我有一个活动及其子片段共享的ViewModel。ViewModel包含一个简单的字符串,我想从活动中更新它,并在片段中观察它。 我的问题很简单:LiveData更新后,我的片段中永远不会到达observe回调。为了进行测试,我尝试在中观察数据,但效果很好。此外,在我在其他ViewModels中声明的片段中观察LiveData变量也可以很好地工作。奇怪的是,只有这个Vi