https://www.mongodb.com/docs/realm/sdk/kotlin/realm-database/delete/delete-all-objects-of-a-type/
I am learning new kotlin-realm in my project. But i dont know how to delete objects. It keep showing error Caused by: io.realm.internal.interop.RealmCoreNotInATransactionException: [5]: Must be in a write transaction
this is the code :
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val realm by lazy { (application as CustomApplication).realm }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
realm.writeBlocking {
copyToRealm(Buku(
name = "Perjuangan Menjual Baju"
))
copyToRealm(Buku(
name = "Perang Saudara"
))
}
val buku = realm.query<Buku>("name BEGINSWITH $0", "pera")
Log.i("AOEU", "buku = $buku")
CoroutineScope(Dispatchers.Main).launch {
val query = realm.query<Buku>().find()
realm.write {
delete(query)
}
}
}
}
After days of finding solution. I just realized that the only mistake in my code is
val query = realm.query().find()
Which is should be replaced with
val query = this.query().find()
Related
I am confused about how flow.collect works. Because in the lifecycleScope below I already say that a should be assigned by the value of data in my database. However, the value of a is still the string of "Hi" instead of "Hello".
class MainActivity : AppCompatActivity() {
private var binding: ActivityMainBinding? = null
private var a: String = "Hi"
override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityMainBinding.inflate(layoutInflater)
super.onCreate(savedInstanceState)
setContentView(binding?.root)
val somethingDao = SomethingDatabase.getDatabase(this).somethingDao()
lifecycleScope.launch {
somethingDao.insert(SomethingModel("Hello"))
somethingDao.fetchAllSomething().collect {
a = it[it.size - 1].name
}
}
println(a)
}
}
this is all of the information in my database
lifecycleScope.launch will start a coroutine, to make it simple the code inside lifecycleScope.launch will be executed in another thread and it will take some time until inserting data and reading it from database, but println(a) is on the main thread so it will be executed before this line a = it[it.size - 1].name, so your println(a) should be inside lifecycleScope.launch like this:
class MainActivity : AppCompatActivity() {
private var binding: ActivityMainBinding? = null
private var a: String = "Hi"
override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityMainBinding.inflate(layoutInflater)
super.onCreate(savedInstanceState)
setContentView(binding?.root)
val somethingDao = SomethingDatabase.getDatabase(this).somethingDao()
lifecycleScope.launch {
somethingDao.insert(SomethingModel("Hello"))
somethingDao.fetchAllSomething().collect {
a = it[it.size - 1].name
println(a)
}
}
}
}
Note: take a look on kotlin coroutines to better understand
In my application I want use Koin , Room and LiveData.
I write below codes, but after add new item into room not auto update recyclerview list!
Should close app and open again for show updated list !
Dao codes :
#Query("SELECT * FROM $NOTE_TABLE")
fun getAllNote(): MutableList<NoteModel>
Repository codes :
class RoomRepository(private val dao: NoteDao) {
suspend fun saveNote(note: NoteModel) = dao.saveNote(note)
fun getAllNotes() = dao.getAllNote()
}
ViewModel codes:
class RoomViewModel(private val repository: RoomRepository) : ViewModel() {
val notesList = MutableLiveData<MutableList<NoteModel>>()
fun saveNote(note:NoteModel) = viewModelScope.launch {
repository.saveNote(note)
}
fun loadAllNotes() = viewModelScope.launch {
val list = repository.getAllNotes()
if (list.isNotEmpty()) {
notesList.postValue(list)
}
}
}
Activity codes :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityKoinRoomBinding.inflate(layoutInflater)
setContentView(binding.root)
//InitViews
binding.apply {
//Save
btnSave.setOnClickListener {
val title = titleEdt.text.toString()
note.id = 0
note.title = title
viewModel.saveNote(note)
}
//Load notes
viewModel.loadAllNotes()
viewModel.notesList.observe(this#KoinRoomActivity) {
noteAdapter.differ.submitList(it)
notesList.apply {
layoutManager = LinearLayoutManager(this#KoinRoomActivity)
adapter = noteAdapter
}
}
}
How can I fix this issue?
In order to update data immediately, you need to return LiveData<T> from the database itself. In your case, do something like that:
#Query("SELECT * FROM $NOTE_TABLE")
fun getAllNote(): LiveData<List<NoteModel>>
I also changed MutableList to List, because there is no need for mutability here.
You ViewModel can then be like this:
class RoomViewModel(private val repository: RoomRepository) : ViewModel() {
val notesList = repository.getAllNotes()
...
}
and you can also remove function loadAllNotes() from it.
This is what I want to achieve. And please help me with the regex for the third error.
You need to use isErrorEnabled and error atributes of your TextInputLayout instance.
const val PASSWORD_PATTERN = ...// your regex
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.checkPasswordButton.setOnClickListener {
val password = binding.passwordEditText.text.toString()
val isPasswordValid =
Pattern.compile(PASSWORD_PATTERN).matcher(password).matches()
binding.passwordInputLayout.isErrorEnabled = !isPasswordValid
val passwordError = if (isPasswordValid) "" else
getString(R.string.invalid_password)
binding.passwordInputLayout.error = passwordError
}
}
}
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
getCurrentCountry()
}
private fun getCurrentCountry(){
val api = Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build().create(CountryReq::class.java)
GlobalScope.launch(Dispatchers.IO) {
val response = api.getCountries().awaitResponse()
if(response.isSuccessful){
val data = response.body()!!
withContext(Dispatchers.Main){
binding.selectCountry.text = "Demo text"
}
}
}
}
}
I'm trying to get data from an API and display it in a textview. But I can't seem to access the views or change its values from the GlobalScope.launch{} block.
I dont understand where in mvvm model object should be store.
For e.g i have app
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
viewModel.userScore.observe(this, Observer { it->
score_view.text = it.toString()
})
score_bt.setOnClickListener {
viewModel.scorePoint()
}
}
}
class MyViewModel: ViewModel() {
val _userScore = MutableLiveData<Int>()
val userScore: LiveData<Int>
get() = _userScore
init {
_userScore.value = 1
}
fun scorePoint(){
_userScore.value = (_userScore.value)?.plus(1)
}
}
class Game {
val score = 0
}
when user click button the score increase. I want to store the score in object class Game. Where should the object be stored and how to connect the object with viewmodel, because I think that viewmodel shouldn't contain the object. To be clear I don't expect to stored that object when user turn off app.
Object Game
class Game {
var score = 0
}
The ViewModel
class MyViewModel: ViewModel() {
val game = Game() //init the object
val _userScore = MutableLiveData<Game>()
val userScore: LiveData<Game>
get() = _userScore
init {
_userScore.value = game.apply {
score = 1
}
}
fun scorePoint(){
_userScore.value = game.apply {
score++
}
}
}