I have a simple app that contains a TextView and stores data in a room database When the database contains information, the data is displayed in the text view
problem When I read the data from the room database and show the first time in the text view with the ViewModel that the database is empty for the first time, the application crashes! I have tested it with Recyclerview, well the recyclerview was empty
Question Why does the program not show the empty text view and it crashes, but this is not the case in Recycler View? How can I show the data in the text view?
my code in fragment
class HomeFragment : Fragment() {
private lateinit var viewModel: MyViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this)[MyViewModel::class.java]
viewModel.getAllDataObservers().observe(viewLifecycleOwner){
//textview for show data
txt_show_number.text = it[0].question_number
txt_show_question.text = it[0].question
}
}
}
ViewModel
class MyViewModel(application: Application) : AndroidViewModel(application) {
var allUsers: MutableLiveData<List<EntityStudent>> = MutableLiveData()
fun getAllDataObservers(): MutableLiveData<List<EntityStudent>> {
getAllData()
return allUsers
}
fun getAllData() {
val dao = RoomDb.getAppDatabase((getApplication()))?.mainDao()
val list = dao?.getAllData()
allUsers.postValue(list!!)
}
fun insert(entityStudent: EntityStudent) {
val dao = RoomDb.getAppDatabase((getApplication()))?.mainDao()
val list = dao?.insert(entityStudent)
getAllData()
} }
CodePudding user response:
It is possible that you are referencing to element which does not exist, in this line:
txt_show_number.text = it[0].question_number
Try to check if list in MutableLiveData object is not empty, for example:
viewModel.getAllDataObservers().observe(viewLifecycleOwner){
if(it.size > 0){
//textview for show data
txt_show_number.text = it[0].question_number
txt_show_question.text = it[0].question
}
}
By the way - resolving your problem would be much easier, if you would attach crash error message from logcat, please kindly attach it next time.
CodePudding user response:
I suspect the error goes like: "Cannot access database on the main thread since it may potentially lock the UI for a long periods of time." because you are not calling database with view model coroutines :)
ViewModel is supposed to call it like:
viewModelScope.launch(Dispatchers.IO) {...dbcall...}
(not recommended though - dispatchers should be injected as docs say)
These operations are synced, so they are called in coroutine to dodge ui blocking.
Another topic is that you're using indexes, like it[0] which is very very bad habbit.
I think there is sufficient information how to start with ROOM, coroutines and viewmodels so I won't spam.