1

My observer is working and it's getting called whenever a new record is entered,

The problem is with recycler view is only showing one record to begin with and it never updates itself to show additional records as a result of save setClickListener.

I can verify in the my database (Room with LiveData) that I've more than one record, there's some problem with the Adapter or the ViewHolder.

P.S. Plus any modifications to how things should be done when it comes to patterns with adapter are most welcome. I hope I got it right.

MainActivity onCreate method

    viewModel = ViewModelProvider(this).get(BookViewModel::class.java)

    save.setOnClickListener {
        val book = Book(UUID.randomUUID().toString(), "author 2", "book 2")
        viewModel.insert(book)
    }

    val bookListAdapter = BookListAdapter(this)
    recyclerView.adapter = bookListAdapter
    recyclerView.layoutManager = LinearLayoutManager(this)

    viewModel.allBooks.observe(this, Observer { books ->
        books?.let {
            Log.d(TAG, "onCreate: changed")
            bookListAdapter.setBooks(books)
        }
    })

static classes in MainActivity

private class BookListAdapter(private val context: Context): RecyclerView.Adapter<BookListAdapter.BookViewHolder>() {

    private var bookList: List<Book> = mutableListOf()

    // getting called only once
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookListAdapter.BookViewHolder {
        val itemView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false)
        return BookViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: BookListAdapter.BookViewHolder, position: Int) {
        val book = bookList[position]
        holder.setData(book.author, book.book, position)
    }

    override fun getItemCount(): Int {
        Log.d("inner", "getItemCount: ${bookList.size}") // this return correct size
        return bookList.size
    }

    fun setBooks(it: List<Book>?) {
        bookList = it!!
        notifyDataSetChanged()
    }

    private class BookViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {

        fun setData(a: String, b: String, p: Int) {
            itemView.author.text = a
            itemView.book.text = b
        }
    }

}
AppDeveloper
  • 1,191
  • 1
  • 12
  • 30

1 Answers1

0

Based on this answer: How to update RecyclerView Adapter Data? I think that You have to notifyDataSetChanged from observer method not inside the adapter class.

viewModel.allBooks.observe(this, Observer { books ->
    books?.let {
        Log.d(TAG, "onCreate: changed")
        bookListAdapter.setBooks(books)
        bookListAdapter.notifyDataSetChanged()
    }
})
fun setBooks(it: List<Book>) {
    bookList = it
}

Also, when You use Room I think You can try to use DiffUtil. It will automatically refresh layout when it has to be refreshed and is much faster than calling notifyDataSetChanged every time Your data is changed.

iknow
  • 4,796
  • 9
  • 19
  • 37