I have an edit text and a button. If I click on the button the data of the edit text gets inserted into my List which a live data. I want to show the items of the list in the recycler view but its not showing any data. I think the observer is not getting called as it is showing greyish (same as when we declare a variable or function and we don't use it) or may be there is something else happening.
This is the only activity class
class MainActivity : AppCompatActivity(), NoteAdapter.OnItemClicked {
private lateinit var recyclerView: RecyclerView
private lateinit var btnAdd: Button
private lateinit var etNote: EditText
lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView = findViewById(R.id.recyclerView)
btnAdd = findViewById(R.id.btn_add)
etNote = findViewById(R.id.et_note)
val mAdapter = NoteAdapter(this, this)
recyclerView.apply {
adapter = mAdapter
layoutManager = LinearLayoutManager(this#MainActivity)
}
viewModel = ViewModelProvider(this,
ViewModelProvider.AndroidViewModelFactory.getInstance(application))[MyViewModel::class.java]
viewModel.allNotes.observe(this, Observer {
it?.let {
mAdapter.updateList(it)
}
})
btnAdd.setOnClickListener {
addNote()
}
}
override fun onClick(note: Notes) {
viewModel.delete(note)
}
private fun addNote(){
val note: String = etNote.text.toString()
if(note.isNotBlank()) {
viewModel.insert(Notes(note))
Toast.makeText(this, "$note inserted", Toast.LENGTH_SHORT).show()
}
}
}
And this is my adapter
class NoteAdapter(private val context: Context, private val clickListener: OnItemClicked) : RecyclerView.Adapter<NoteAdapter.MyViewHolder>() {
private val allNotes = mutableListOf<Notes>()
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvNoteItem: TextView = itemView.findViewById(R.id.tv_note)
val ivDelete: ImageView = itemView.findViewById(R.id.iv_delete)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.note_item, parent, false)
val viewHolder = MyViewHolder(view)
viewHolder.ivDelete.setOnClickListener{
clickListener.onClick(allNotes[viewHolder.adapterPosition])
}
return viewHolder
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentNote = allNotes[position]
holder.apply {
tvNoteItem.text = currentNote.note
}
}
override fun getItemCount() = allNotes.size
interface OnItemClicked{
fun onClick(note: Notes)
}
fun updateList(newList: List<Notes>){
allNotes.clear()
allNotes.addAll(newList)
notifyDataSetChanged()
}
}
#Entity(tableName = "notes_table")
data class Notes(val note: String) {
#PrimaryKey(autoGenerate = true)
var id = 0
}
Dao:
#Dao
interface NotesDao {
#Insert
suspend fun insertNote(note: Notes){ //Suspended means it will run it background thread
}
#Delete
suspend fun deleteNotes(note: Notes){
}
#Query("Select * from notes_table order by id")
fun getAllNotes(): LiveData<List<Notes>>
}
Database:
#Database(entities = arrayOf(Notes::class), version = 1, exportSchema = false)
abstract class NoteDatabase : RoomDatabase() {
abstract fun noteDao() : NotesDao
companion object{
// Singleton prevents multiple instances of database opening at the
// same time.
#Volatile
private var INSTANCE: NoteDatabase? = null
fun getDatabase(context: Context): NoteDatabase {
// if the INSTANCE is not null, then return it,
// if it is, then create the database
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java,
"notes_table"
).build()
INSTANCE = instance
// return instance
instance
}
}
}
}
This is viewModel class
class MyViewModel(application: Application) : AndroidViewModel(application) {
private val repository: NotesRepository
val allNotes : LiveData<List<Notes>>
init {
val dao = NoteDatabase.getDatabase(application).noteDao()
repository = NotesRepository(dao)
allNotes = repository.noteList
}
fun delete(note: Notes) = viewModelScope.launch(Dispatchers.IO) {
repository.delete(note)
}
fun insert(note: Notes) = viewModelScope.launch(Dispatchers.IO) {
repository.insert(note)
}
}
Here is my repository class
class NotesRepository(private val dao: NotesDao) {
val noteList = dao.getAllNotes()
suspend fun insert(note: Notes){
dao.insertNote(note)
}
suspend fun delete(note: Notes){
dao.deleteNotes(note)
}
}
Related
I have an editText and a button. When I click on the button the data from the edittext gets inserted into the database. On the save activity I have recyclerView which will show the items getting from the viewModel. I have put the observer to observer the data but it is not showing any item in the recuclerView.
class MainActivity : AppCompatActivity(), NoteAdapter.OnItemClicked {
private lateinit var recyclerView: RecyclerView
private lateinit var btnAdd: Button
private lateinit var etNote: EditText
lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView = findViewById(R.id.recyclerView)
btnAdd = findViewById(R.id.btn_add)
etNote = findViewById(R.id.et_note)
val mAdapter = NoteAdapter(this)
recyclerView.apply {
adapter = mAdapter
layoutManager = LinearLayoutManager(this#MainActivity)
}
viewModel = ViewModelProvider(this,
ViewModelProvider.AndroidViewModelFactory.getInstance(application))[MyViewModel::class.java]
viewModel.allNotes.observe(this, Observer {note->
note?.let {
mAdapter.submitList(it)
}
})
btnAdd.setOnClickListener {
addNote()
}
}
override fun onClick(note: Notes) {
viewModel.delete(note)
}
private fun addNote(){
val note: String = etNote.text.toString()
if(note.isNotEmpty()) {
viewModel.insert(Notes(note))
Toast.makeText(this, "$note inserted", Toast.LENGTH_SHORT).show()
}
}
}
Adapter Class
class NoteAdapter(private val clickListener: OnItemClicked)
: ListAdapter<Notes, NoteAdapter.MyViewHolder>(NoteComparator()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.note_item, parent, false)
val viewHolder = MyViewHolder(view)
viewHolder.ivDelete.setOnClickListener{
clickListener.onClick(getItem(viewHolder.adapterPosition))
}
return viewHolder
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentNote = getItem(position)
holder.apply {
tvNoteItem.text = currentNote.note
}
}
interface OnItemClicked{
fun onClick(note: Notes)
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvNoteItem: TextView = itemView.findViewById(R.id.tv_note)
val ivDelete: ImageView = itemView.findViewById(R.id.iv_delete)
}
class NoteComparator : DiffUtil.ItemCallback<Notes>(){
override fun areItemsTheSame(oldItem: Notes, newItem: Notes): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: Notes, newItem: Notes): Boolean {
return oldItem == newItem
}
}
}
ViewModel Class
class MyViewModel(application: Application) : AndroidViewModel(application) {
private val repository: NotesRepository
val allNotes : LiveData<List<Notes>>
init {
val dao = NoteDatabase.getDatabase(application).noteDao()
repository = NotesRepository(dao)
allNotes = repository.noteList
}
fun delete(note: Notes) = viewModelScope.launch(Dispatchers.IO) {
repository.delete(note)
}
fun insert(note: Notes) = viewModelScope.launch(Dispatchers.IO) {
repository.insert(note)
}
}
Heey Divyansh,
Analyzing your code I believe the problem is in your ViewModel. You are trying to change the property allNotes, which is a LiveData. You need mutable live data, so declare it like private because we can't expose a mutable property. And your allNotes property will receive the changes from this mutable property, like this:
class MyViewModel: ViewModel() {
private val _allNotes = MutableLiveData<List<Notes>>(emptyList())
val allNotes: LiveData<List<Notes>>
get() = _allNotes
}
Then, update the mutable live data:
class MyViewModel: ViewModel() {
// ...
init {
val dao = NoteDatabase.getDatabase(application).noteDao()
repository = NotesRepository(dao)
_allNotes.value = repository.noteList
}
}
I have found why it is not displaying the items because the viewModel is not inserting the the data as I have used Dispatcher.IO in the viewModel scope.
I removed it and now it is inserting and showing the items.
Here I've a deleteButton to delete the desired the item from the database and recyclerview. In onSetClickListener of this deleteButton I am calling a function deletePlayerHistory(positon) and passing the position from onBindViewHolder() function for the item user wants to delete.
Adapter Class:
class FriendHistoryAdapter(private var friendHistoryData: List<FriendHistoryData>) :
RecyclerView.Adapter<FriendHistoryAdapter.FriendHistoryHolder>() {
class FriendHistoryHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textViewPlayer1: TextView = itemView.findViewById(R.id.text_view_player_one_name)
val textViewPlayer2: TextView = itemView.findViewById(R.id.text_view_player_second_name)
val textViewScore: TextView = itemView.findViewById(R.id.text_view_score)
val textViewWhoWon: TextView = itemView.findViewById(R.id.text_view_player_won)
val deleteButton: Button = itemView.findViewById(R.id.button_delete)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendHistoryHolder {
val itemView: View = LayoutInflater.from(parent.context)
.inflate(R.layout.friend_history_item, parent, false)
return FriendHistoryHolder(itemView)
}
#SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: FriendHistoryHolder, position: Int) {
holder.textViewPlayer1.text = friendHistoryData[position].playerOneName
holder.textViewPlayer2.text = friendHistoryData[position].playerSecondName
holder.textViewScore.text =
"Score: ${friendHistoryData[position].playerOneScore}-${friendHistoryData[position].playerSecondScore}"
when {
friendHistoryData[position].playerOneScore > friendHistoryData[position].playerSecondScore ->
holder.textViewWhoWon.text = "${friendHistoryData[position].playerOneName} won!"
friendHistoryData[position].playerOneScore < friendHistoryData[position].playerSecondScore ->
holder.textViewWhoWon.text =
"${friendHistoryData[position].playerSecondName} won!"
else -> holder.textViewWhoWon.text = "Draw!"
}
holder.deleteButton.setOnClickListener {
deletePlayerHistory(position)
}
}
override fun getItemCount(): Int {
return friendHistoryData.size
}
private fun deletePlayerHistory(position: Int) {
}
}
Database:
#Database(entities = [FriendHistoryData::class], version = 1)
abstract class FriendHistoryDatabase : RoomDatabase() {
abstract fun friendHistoryDao(): FriendHistoryDao
companion object {
#Volatile
private var instance: FriendHistoryDatabase? = null
#Synchronized
fun getInstance(context: Context): FriendHistoryDatabase? {
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
FriendHistoryDatabase::class.java, "friend_history_database"
).build()
}
return instance
}
}
}
Dao:
#Dao
interface FriendHistoryDao {
#Insert
fun addHistory(friendHistoryData: FriendHistoryData)
#Query("SELECT * FROM friend_history ORDER BY id DESC")
fun getWholeHistory() : List<FriendHistoryData>
#Delete
fun deleteHistory(friendHistoryData: FriendHistoryData)
}
Activity with RecyclerView:
class VsFriendHistory : AppCompatActivity() {
private lateinit var friendHistoryWholeData: List<FriendHistoryData>
private lateinit var friendRecyclerView: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_vs_friend_history)
friendRecyclerView = findViewById(R.id.friend_recycler_view)
friendRecyclerView.layoutManager = LinearLayoutManager(this)
friendRecyclerView.setHasFixedSize(true)
showWholeHistory()
}
private fun showWholeHistory() {
class ShowWholeHistory : AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg params: Void?): Void? {
lateinit var friendHistoryDao: FriendHistoryDao
val database: FriendHistoryDatabase? = application?.let {
FriendHistoryDatabase.getInstance(it)
}
if (database != null) {
friendHistoryDao = database.friendHistoryDao()
}
friendHistoryWholeData = friendHistoryDao.getWholeHistory()
friendRecyclerView.adapter = FriendHistoryAdapter(friendHistoryWholeData)
return null
}
override fun onPostExecute(result: Void?) {
super.onPostExecute(result)
if (friendHistoryWholeData.isEmpty()) {
Toast.makeText(baseContext, "No history to show", Toast.LENGTH_SHORT).show()
}
}
}
ShowWholeHistory().execute()
}
}
Data Class:
#Entity(tableName = "friend_history")
data class FriendHistoryData(
val playerOneName: String,
val playerSecondName: String,
val playerOneScore: Int,
val playerSecondScore: Int
) {
#PrimaryKey(autoGenerate = true)
var id = 0
}
Please help me in completing the deletePlayerHistory() function.
Thanks in advance.
Pass in your FriendHistoryAdapter a friendHistoryDao
it should look like this:
class FriendHistoryAdapter(
private var friendHistoryData: List<FriendHistoryData>,
private val friendHistoryDao: FriendHistoryDao
) { ....
And your method where you delete should look like this:
private fun deletePlayerHistory(position: Int) {
val item = friendHistoryData[position]
(friendHistoryData as MutableList).remove(item)
notifyItemChanged(position)
friendHistoryDao.deleteHistory(item)
}
Try and tell me if it works
The data in the RecyclerView is called the first time without issues. However when i refresh the data, for some reason all the items goes blank.
The MainActivity is this
class BusinessActivity : AppCompatActivity() {
private val businessViewModel: BusinessViewModel by viewModel()
private val imageLoader: ImageLoader by inject()
private lateinit var staggeredGridLayoutManager: StaggeredGridLayoutManager
private lateinit var skeleton: Skeleton
private val adapter: BusinessAdapter by lazy { BusinessAdapter(imageLoader, businessViewModel) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_business)
initToolbar()
skeleton = findViewById<SkeletonLayout>(R.id.skeletonLayout)
staggeredGridLayoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
staggeredGridLayoutManager.gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS
recycler_view.apply {
layoutManager = staggeredGridLayoutManager
adapter = this#BusinessActivity.adapter
setHasFixedSize(true)
}
setupSkeleton()
initializeObserverBusiness()
refreshBusiness.setOnRefreshListener {
refreshBusiness.isRefreshing = true
skeleton.showSkeleton()
businessViewModel.retrieveBusiness()
}
}
private fun initToolbar() {
setSupportActionBar(toolbar)
supportActionBar?.title = getString(R.string.app_name)
this.setSystemBarColor(this)
}
private fun setupSkeleton(){
skeleton = recycler_view.applySkeleton(R.layout.business_card, 6)
skeleton.showSkeleton()
}
private fun initializeObserverBusiness(){
businessViewModel.uiState.observe(this, Observer {
val dataState = it ?: return#Observer
if (!dataState.showProgress){
refreshBusiness.isRefreshing = false
skeleton.showOriginal()
}
if (dataState.business != null && !dataState.business.consumed){
dataState.business.consume()?.let { business ->
adapter.submitList(business)
}
}
if (dataState.error != null && !dataState.error.consumed){
dataState.error.consume()?.let { error ->
Toast.makeText(this, resources.getString(error), Toast.LENGTH_LONG).show()
}
}
})
}
}
and the Adapter for the RecyclerView, im currently using DiffCallback and ListAdapter due to a better performance.
class BusinessAdapter(var imageLoader: ImageLoader, var viewModel: BusinessViewModel) : ListAdapter<Business, BusinessViewHolder>(DIFF_CALLBACK){
companion object{
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Business>() {
override fun areItemsTheSame(oldItem: Business, newItem: Business) = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Business, newItem: Business) = oldItem == newItem
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = BusinessViewHolder.create(parent)
override fun onBindViewHolder(holder: BusinessViewHolder, position: Int) {
holder.bind(getItem(position), imageLoader, viewModel)
}
}
and the ViewHolder for the Adapter
class BusinessViewHolder constructor(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer {
fun bind(business: Business, imageLoader: ImageLoader, viewModel: BusinessViewModel) {
businessImage?.let { imageLoader.load("${BuildConfig.MY_URL}/gallery/${business.images[0]}", it) }
ownerBusiness.text = business.owner
businessName.text = business.name
cardBusiness.setOnClickListener {
viewModel.callDetailBusiness(business.id)
}
}
companion object {
fun create(parent: ViewGroup): BusinessViewHolder {
return BusinessViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.business_card, parent, false))
}
}
}
and the ViewModel
class BusinessViewModel (private val businessRepository: BusinessRepository): ViewModel() {
private val _uiState = MutableLiveData<BusinessDataState>()
val uiState: LiveData<BusinessDataState> get() = _uiState
val _showDetailBusiness = MutableLiveData<Int?>()
val showDetailBusiness: LiveData<Int?> get() = _showDetailBusiness
init {
retrieveBusiness()
}
fun retrieveBusiness(){
viewModelScope.launch {
runCatching {
emitUiState(showProgress = true)
businessRepository.retrieveBusiness()
}.onSuccess {
emitUiState(business = Event(it))
}.onFailure {
emitUiState(error = Event(R.string.internet_failure_error))
}
}
}
fun callDetailBusiness(businessId: Int) {
_showDetailBusiness.value = businessId
}
private fun emitUiState(showProgress: Boolean = false, business: Event<List<Business>>? = null, error: Event<Int>? = null){
val dataState = BusinessDataState(showProgress, business, error)
_uiState.value = dataState
}
data class BusinessDataState(val showProgress: Boolean, val business: Event<List<Business>>?, val error: Event<Int>?)
}
When the data is loaded for the first time i see this.
however when i apply the SwipeRefresh. I receive the data.
D/OkHttp: [{"id":18,"name":"Whatsup","owner":"Mi
Soledad","category":"ToDo",
but the RecyclerView won't attach the new information...
I am getting started for using Mvvm architecture, but I am facing problem with my adapter -> It never called
I have an adapter here :
class LocationResultAdapter: RecyclerView.Adapter<LocationResultAdapter.ViewHolder>() {
private lateinit var resultList:List<ResultSearchBean>
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding: ItemPostBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.item_post, parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(resultList[position])
}
override fun getItemCount(): Int {
return if (resultList.isNotEmpty()) {
resultList.size
} else {
0
}
}
fun updateList(list: List<ResultSearchBean>) {
resultList = list
notifyDataSetChanged()
}
class ViewHolder(private val binding: ItemPostBinding):RecyclerView.ViewHolder(binding.root){
private val viewModel = LocationViewModel()
fun bind(resultSearchBean: ResultSearchBean){
viewModel.bind(resultSearchBean)
binding.viewModel = viewModel
}
}
}
this adapter is called in my ViewModel
class LocationResultViewModel(private val resultSearchDao: ResultSearchDao): BaseViewModel() {
#Inject
lateinit var mFi9Api: Fi9Api
private lateinit var mSubscription: Disposable
var mSearchText: String = ""
val adapter: LocationResultAdapter = LocationResultAdapter()
override fun onCleared() {
super.onCleared()
mSubscription.dispose()
}
fun search(searchText: String) {
resultLocations(searchText)
}
private fun resultLocations(searchText: String) {
mSearchText = searchText
mSubscription = mFi9Api.getLocation(mSearchText)
.flatMap { resource ->
return#flatMap Observable.fromCallable {
resultSearchDao.deleteAll()
resultSearchDao.insertAll(resource.distinctBy { r -> r.label })
}
}
.concatMap {
return#concatMap resultSearchDao.all()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(GetLocationListSubscriber())
}
inner class GetLocationListSubscriber : ResourceObserver<List<ResultSearchBean>>() {
override fun onNext(#NonNull t: List<ResultSearchBean>) {
adapter.updateList(t)
}
override fun onError(#NonNull e: Throwable) {
}
override fun onComplete() {
// Nothing to do
}
}
In my activity I have this following code :
class LocationResultActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: LocationResultViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.resultList.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
viewModel = ViewModelProviders.of(this, ViewModelFactory(this)).get(LocationResultViewModel::class.java)
binding.viewModel = viewModel
search_btn.setOnClickListener {
viewModel.search(search_et.text.toString())
}
}
}
Only the method: adapter.updateList(t) is called.
I put some break point on onCreateViewHolder, OnBindViewHolder, getItemCount but it never called
What did I do that does not work?
Thank you for your help
I think you need to assign your adapter to your RecyclerView.
Try this:
binding.resultList.adapter = viewModel.adapter
I would like to show my items in a recycler view via RoomDatabase. But when I start application - it shows empty screen with only title.
It's an adapter for recycler view
class AlarmAdapter : ListAdapter<Alarm, AlarmAdapter.AlarmHolder>(DIFF_CALLBACK) {
private lateinit var alarmViewModel: AlarmViewModel
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Alarm>() {
override fun areItemsTheSame(oldItem: Alarm, newItem: Alarm): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Alarm, newItem: Alarm): Boolean {
return oldItem.days == newItem.days && oldItem.timeInMinutes == newItem.timeInMinutes
&& oldItem.departTimeInMinutes == newItem.departTimeInMinutes && oldItem.fromAddress == newItem.fromAddress
&& oldItem.toAddress == newItem.toAddress && oldItem.isEnabled == newItem.isEnabled
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AlarmHolder {
val itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.alarm_item, parent, false)
alarmViewModel = ViewModelProviders.of(parent.context as FragmentActivity).get(AlarmViewModel::class.java)
return AlarmHolder(itemView)
}
override fun onBindViewHolder(holder: AlarmHolder, position: Int) {
val currentAlarm = getItem(position)
holder.fromAddress.text = currentAlarm.fromAddress
// and other texts
holder.alarmSwitch.isEnabled = currentAlarm.isEnabled
holder.alarmSwitch.setOnClickListener {
holder.alarmSwitch.toggle()
currentAlarm.isEnabled = !currentAlarm.isEnabled
alarmViewModel.update(currentAlarm)
}
}
inner class AlarmHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
internal var fromAddress = itemView.findViewById<TextView>(R.id.alarm_item_from_address)
// and other resources
}
}
Here is a part of MainActivity
class MainActivity : AppCompatActivity() {
companion object {
private const val DAY_MINUTES = 24 * 60
}
private var currentEditAlarmDialog: EditAlarmDialog? = null
private lateinit var alarmViewModel: AlarmViewModel
private lateinit var adapter: AlarmAdapter
private lateinit var layoutManager: LinearLayoutManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_YES
setContentView(R.layout.activity_main)
layoutManager = LinearLayoutManager(this)
recycler_view.layoutManager = layoutManager
recycler_view.setHasFixedSize(true)
adapter = AlarmAdapter()
recycler_view.adapter = adapter
alarmViewModel = ViewModelProviders.of(this).get(AlarmViewModel::class.java)
alarmViewModel.getAllAlarms().observe(this, Observer<List<Alarm>> {
adapter.submitList(it)
})
}
AlarmViewModel class
class AlarmViewModel(application: Application) : AndroidViewModel(application) {
private val repository = AlarmRepository(application)
private val allAlarms = repository.getAllAlarms()
fun insert(alarm: Alarm) {
repository.insert(alarm)
}
fun update(alarm: Alarm) {
repository.update(alarm)
}
fun delete(alarm: Alarm) {
repository.delete(alarm)
}
fun deleteAllAlarms() {
repository.deleteAllNotes()
}
fun getAllAlarms() = allAlarms
fun getAlarmById(id: Int) = repository.getAlarmById(id)
}
It is a repository
class AlarmRepository(application: Application) {
private var alarmDao: AlarmDao
private var allAlarms: LiveData<List<Alarm>>
private val uiScope = CoroutineScope(Dispatchers.IO)
init {
val database: AlarmDatabase = AlarmDatabase.getInstance(application.applicationContext)!!
alarmDao = database.alarmDao()
allAlarms = alarmDao.getAllAlarms()
}
fun getAllAlarms() = allAlarms
fun insert(alarm: Alarm) {
uiScope.launch { alarmDao.insert(alarm) }
}
fun delete(alarm: Alarm) {
uiScope.launch { alarmDao.delete(alarm) }
}
fun deleteAllNotes() {
uiScope.launch { alarmDao.deleteAllAlarms() }
}
fun update(alarm: Alarm) {
uiScope.launch { alarmDao.update(alarm) }
}
fun getAlarmById(id: Int) = alarmDao.getAlarmById(id)
}
And the Dao class
#Dao
interface AlarmDao {
#Insert
fun insert(alarm: Alarm)
#Delete
fun delete(alarm: Alarm)
#Update
fun update(alarm: Alarm)
#Query("DELETE FROM alarm_table")
fun deleteAllAlarms()
#Query("SELECT * FROM alarm_table ORDER BY days ASC")
fun getAllAlarms() : LiveData<List<Alarm>>
#Query("SELECT * FROM alarm_table WHERE id = :id")
fun getAlarmById(id: Int) : Alarm
}
What can I do to solve this problem?
If you need more code - just tell me about that!
In your AlarmViewModel class, put the call to the repo in the getAllAlarms method.
fun getAllAlarms() {
repository.getAllAlarms()
}
remove this from init method
allAlarms = alarmDao.getAllAlarms()
and put
fun getAllAlarms() = alarmDao.getAllAlarms()